webservices: Add support for decoding supplementary characters' references.
[wine.git] / dlls / webservices / reader.c
bloba6f5d6bc94ba0111b020b23cb4ff4aa3eb03d704
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)
1170 return -1;
1171 if (cp < 0x80)
1173 *dst = cp;
1174 return 1;
1176 if (cp < 0x800)
1178 dst[1] = 0x80 | (cp & 0x3f);
1179 cp >>= 6;
1180 dst[0] = 0xc0 | cp;
1181 return 2;
1183 if ((cp >= 0xd800 && cp <= 0xdfff) || cp == 0xfffe || cp == 0xffff) return -1;
1184 if (cp < 0x10000)
1186 dst[2] = 0x80 | (cp & 0x3f);
1187 cp >>= 6;
1188 dst[1] = 0x80 | (cp & 0x3f);
1189 cp >>= 6;
1190 dst[0] = 0xe0 | cp;
1191 return 3;
1193 if (cp >= 0x110000) return -1;
1194 dst[3] = 0x80 | (cp & 0x3f);
1195 cp >>= 6;
1196 dst[2] = 0x80 | (cp & 0x3f);
1197 cp >>= 6;
1198 dst[1] = 0x80 | (cp & 0x3f);
1199 cp >>= 6;
1200 dst[0] = 0xf0 | cp;
1201 return 4;
1204 static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char *ret, ULONG *ret_len )
1206 const unsigned char *p = str;
1207 unsigned char *q = ret;
1209 *ret_len = 0;
1210 while (len)
1212 if (*p == '&')
1214 p++; len--;
1215 if (!len) return WS_E_INVALID_FORMAT;
1217 if (len >= 3 && !memcmp( p, "lt;", 3 ))
1219 *q++ = '<';
1220 p += 3;
1221 len -= 3;
1223 else if (len >= 3 && !memcmp( p, "gt;", 3 ))
1225 *q++ = '>';
1226 p += 3;
1227 len -= 3;
1229 else if (len >= 5 && !memcmp( p, "quot;", 5 ))
1231 *q++ = '"';
1232 p += 5;
1233 len -= 5;
1235 else if (len >= 4 && !memcmp( p, "amp;", 4 ))
1237 *q++ = '&';
1238 p += 4;
1239 len -= 4;
1241 else if (len >= 5 && !memcmp( p, "apos;", 5 ))
1243 *q++ = '\'';
1244 p += 5;
1245 len -= 5;
1247 else if (*p == '#')
1249 ULONG start, nb_digits, i;
1250 int len_utf8, cp = 0;
1252 p++; len--;
1253 if (!len) return WS_E_INVALID_FORMAT;
1254 else if (*p == 'x')
1256 p++; len--;
1258 start = len;
1259 while (len && isxdigit( *p )) { p++; len--; };
1260 if (!len) return WS_E_INVALID_FORMAT;
1262 p -= nb_digits = start - len;
1263 if (!nb_digits || nb_digits > 6 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1264 for (i = 0; i < nb_digits; i++)
1266 cp *= 16;
1267 if (*p >= '0' && *p <= '9') cp += *p - '0';
1268 else if (*p >= 'a' && *p <= 'f') cp += *p - 'a' + 10;
1269 else cp += *p - 'A' + 10;
1270 p++;
1273 else if (isdigit( *p ))
1275 while (len && *p == '0') { p++; len--; };
1276 if (!len) return WS_E_INVALID_FORMAT;
1278 start = len;
1279 while (len && isdigit( *p )) { p++; len--; };
1280 if (!len) return WS_E_INVALID_FORMAT;
1282 p -= nb_digits = start - len;
1283 if (!nb_digits || nb_digits > 7 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1284 for (i = 0; i < nb_digits; i++)
1286 cp *= 10;
1287 cp += *p - '0';
1288 p++;
1291 else return WS_E_INVALID_FORMAT;
1292 p++; len--;
1293 if ((len_utf8 = codepoint_to_utf8( cp, q )) < 0) return WS_E_INVALID_FORMAT;
1294 *ret_len += len_utf8;
1295 q += len_utf8;
1296 continue;
1298 else return WS_E_INVALID_FORMAT;
1300 else
1302 *q++ = *p++;
1303 len--;
1305 *ret_len += 1;
1307 return S_OK;
1310 static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1312 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1313 WS_XML_ATTRIBUTE *attr;
1314 WS_XML_UTF8_TEXT *text = NULL;
1315 unsigned int len = 0, ch, skip, quote;
1316 const unsigned char *start;
1317 WS_XML_STRING *prefix, *localname;
1318 HRESULT hr = WS_E_INVALID_FORMAT;
1320 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1322 start = read_current_ptr( reader );
1323 for (;;)
1325 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1326 if (!read_isnamechar( ch )) break;
1327 read_skip( reader, skip );
1328 len += skip;
1330 if (!len) goto error;
1332 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) goto error;
1333 hr = E_OUTOFMEMORY;
1334 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1336 heap_free( prefix );
1337 attr->isXmlNs = 1;
1338 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1340 heap_free( localname );
1341 goto error;
1343 attr->localName = localname;
1345 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1347 attr->isXmlNs = 1;
1348 attr->prefix = prefix;
1349 attr->localName = localname;
1351 else
1353 attr->prefix = prefix;
1354 attr->localName = localname;
1357 hr = WS_E_INVALID_FORMAT;
1358 read_skip_whitespace( reader );
1359 if (read_cmp( reader, "=", 1 )) goto error;
1360 read_skip( reader, 1 );
1362 read_skip_whitespace( reader );
1363 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) goto error;
1364 quote = read_utf8_char( reader, &skip );
1365 read_skip( reader, 1 );
1367 len = 0;
1368 start = read_current_ptr( reader );
1369 for (;;)
1371 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1372 if (ch == quote) break;
1373 read_skip( reader, skip );
1374 len += skip;
1376 read_skip( reader, 1 );
1378 hr = E_OUTOFMEMORY;
1379 if (attr->isXmlNs)
1381 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1382 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1383 if (!(text = alloc_utf8_text( NULL, 0 ))) goto error;
1385 else
1387 if (!(text = alloc_utf8_text( NULL, len ))) goto error;
1388 if ((hr = decode_text( start, len, text->value.bytes, &text->value.length )) != S_OK) goto error;
1391 attr->value = &text->text;
1392 attr->singleQuote = (quote == '\'');
1394 *ret = attr;
1395 return S_OK;
1397 error:
1398 heap_free( text );
1399 free_attribute( attr );
1400 return hr;
1403 static inline BOOL is_valid_parent( const struct node *node )
1405 if (!node) return FALSE;
1406 return node_type( node ) == WS_XML_NODE_TYPE_ELEMENT || node_type( node ) == WS_XML_NODE_TYPE_BOF;
1409 struct node *find_parent( struct node *node )
1411 if (is_valid_parent( node )) return node;
1412 if (is_valid_parent( node->parent )) return node->parent;
1413 return NULL;
1416 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1418 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1419 const WS_XML_STRING *ns;
1420 ULONG i;
1422 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1423 if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1424 if (!elem->ns->length) elem->ns->bytes = (BYTE *)(elem->ns + 1); /* quirk */
1426 for (i = 0; i < elem->attributeCount; i++)
1428 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1429 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1430 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1431 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1433 return S_OK;
1436 static HRESULT read_element( struct reader *reader )
1438 unsigned int len = 0, ch, skip;
1439 const unsigned char *start;
1440 struct node *node = NULL, *endnode, *parent;
1441 WS_XML_ELEMENT_NODE *elem;
1442 WS_XML_ATTRIBUTE *attr = NULL;
1443 HRESULT hr = WS_E_INVALID_FORMAT;
1445 if (read_end_of_data( reader ))
1447 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1448 reader->last = reader->current;
1449 reader->state = READER_STATE_EOF;
1450 return S_OK;
1453 if (read_cmp( reader, "<", 1 )) goto error;
1454 read_skip( reader, 1 );
1455 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1457 read_rewind( reader, 1 );
1458 goto error;
1461 start = read_current_ptr( reader );
1462 for (;;)
1464 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1465 if (!read_isnamechar( ch )) break;
1466 read_skip( reader, skip );
1467 len += skip;
1469 if (!len) goto error;
1471 if (!(parent = find_parent( reader->current ))) goto error;
1473 hr = E_OUTOFMEMORY;
1474 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error;
1475 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) goto error;
1476 list_add_tail( &node->children, &endnode->entry );
1477 endnode->parent = node;
1479 elem = (WS_XML_ELEMENT_NODE *)node;
1480 if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1482 reader->current_attr = 0;
1483 for (;;)
1485 read_skip_whitespace( reader );
1486 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1487 if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
1488 if ((hr = append_attribute( elem, attr )) != S_OK)
1490 free_attribute( attr );
1491 goto error;
1493 reader->current_attr++;
1495 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1497 read_insert_node( reader, parent, node );
1498 reader->state = READER_STATE_STARTELEMENT;
1499 return S_OK;
1501 error:
1502 destroy_nodes( node );
1503 return hr;
1506 static HRESULT read_text( struct reader *reader )
1508 unsigned int len = 0, ch, skip;
1509 const unsigned char *start;
1510 struct node *node, *parent;
1511 WS_XML_TEXT_NODE *text;
1512 WS_XML_UTF8_TEXT *utf8;
1513 HRESULT hr;
1515 start = read_current_ptr( reader );
1516 for (;;)
1518 if (read_end_of_data( reader )) break;
1519 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1520 if (ch == '<') break;
1521 read_skip( reader, skip );
1522 len += skip;
1525 if (!(parent = find_parent( reader->current ))) return WS_E_INVALID_FORMAT;
1527 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1528 text = (WS_XML_TEXT_NODE *)node;
1529 if (!(utf8 = alloc_utf8_text( NULL, len )))
1531 heap_free( node );
1532 return E_OUTOFMEMORY;
1534 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
1536 heap_free( utf8 );
1537 heap_free( node );
1538 return hr;
1540 text->text = &utf8->text;
1542 read_insert_node( reader, parent, node );
1543 reader->state = READER_STATE_TEXT;
1544 return S_OK;
1547 static HRESULT read_node( struct reader * );
1549 static HRESULT read_startelement( struct reader *reader )
1551 read_skip_whitespace( reader );
1552 if (!read_cmp( reader, "/>", 2 ))
1554 read_skip( reader, 2 );
1555 reader->current = LIST_ENTRY( list_tail( &reader->current->children ), struct node, entry );
1556 reader->last = reader->current;
1557 reader->state = READER_STATE_ENDELEMENT;
1558 return S_OK;
1560 else if (!read_cmp( reader, ">", 1 ))
1562 read_skip( reader, 1 );
1563 return read_node( reader );
1565 return WS_E_INVALID_FORMAT;
1568 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
1570 HRESULT hr;
1572 switch (reader->state)
1574 case READER_STATE_INITIAL:
1575 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
1576 break;
1578 case READER_STATE_STARTELEMENT:
1579 if (found) *found = TRUE;
1580 return S_OK;
1582 default:
1583 break;
1586 read_skip_whitespace( reader );
1587 if ((hr = read_element( reader )) == S_OK && found)
1589 if (reader->state == READER_STATE_STARTELEMENT)
1590 *found = TRUE;
1591 else
1592 *found = FALSE;
1595 return hr;
1598 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
1600 ULONG i;
1601 if (len1 != len2) return 1;
1602 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
1603 return 0;
1606 static struct node *read_find_startelement( struct reader *reader, const WS_XML_STRING *prefix,
1607 const WS_XML_STRING *localname )
1609 struct node *parent;
1610 const WS_XML_STRING *str;
1612 for (parent = reader->current; parent; parent = parent->parent)
1614 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
1616 str = parent->hdr.prefix;
1617 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
1618 str = parent->hdr.localName;
1619 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
1620 return parent;
1623 return NULL;
1626 static HRESULT read_endelement( struct reader *reader )
1628 struct node *parent;
1629 unsigned int len = 0, ch, skip;
1630 const unsigned char *start;
1631 WS_XML_STRING *prefix, *localname;
1632 HRESULT hr;
1634 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
1636 if (read_end_of_data( reader ))
1638 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1639 reader->last = reader->current;
1640 reader->state = READER_STATE_EOF;
1641 return S_OK;
1644 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
1645 read_skip( reader, 2 );
1647 start = read_current_ptr( reader );
1648 for (;;)
1650 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1651 if (ch == '>')
1653 read_skip( reader, 1 );
1654 break;
1656 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
1657 read_skip( reader, skip );
1658 len += skip;
1661 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
1662 parent = read_find_startelement( reader, prefix, localname );
1663 heap_free( prefix );
1664 heap_free( localname );
1665 if (!parent) return WS_E_INVALID_FORMAT;
1667 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
1668 reader->last = reader->current;
1669 reader->state = READER_STATE_ENDELEMENT;
1670 return S_OK;
1673 static HRESULT read_comment( struct reader *reader )
1675 unsigned int len = 0, ch, skip;
1676 const unsigned char *start;
1677 struct node *node, *parent;
1678 WS_XML_COMMENT_NODE *comment;
1680 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
1681 read_skip( reader, 4 );
1683 start = read_current_ptr( reader );
1684 for (;;)
1686 if (!read_cmp( reader, "-->", 3 ))
1688 read_skip( reader, 3 );
1689 break;
1691 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1692 read_skip( reader, skip );
1693 len += skip;
1696 if (!(parent = find_parent( reader->current ))) return WS_E_INVALID_FORMAT;
1698 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
1699 comment = (WS_XML_COMMENT_NODE *)node;
1700 if (!(comment->value.bytes = heap_alloc( len )))
1702 heap_free( node );
1703 return E_OUTOFMEMORY;
1705 memcpy( comment->value.bytes, start, len );
1706 comment->value.length = len;
1708 read_insert_node( reader, parent, node );
1709 reader->state = READER_STATE_COMMENT;
1710 return S_OK;
1713 static HRESULT read_startcdata( struct reader *reader )
1715 struct node *node, *endnode, *parent;
1717 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
1718 read_skip( reader, 9 );
1720 if (!(parent = find_parent( reader->current ))) return WS_E_INVALID_FORMAT;
1722 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
1723 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_CDATA )))
1725 heap_free( node );
1726 return E_OUTOFMEMORY;
1728 list_add_tail( &node->children, &endnode->entry );
1729 endnode->parent = node;
1731 read_insert_node( reader, parent, node );
1732 reader->state = READER_STATE_STARTCDATA;
1733 return S_OK;
1736 static HRESULT read_cdata( struct reader *reader )
1738 unsigned int len = 0, ch, skip;
1739 const unsigned char *start;
1740 struct node *node;
1741 WS_XML_TEXT_NODE *text;
1742 WS_XML_UTF8_TEXT *utf8;
1744 start = read_current_ptr( reader );
1745 for (;;)
1747 if (!read_cmp( reader, "]]>", 3 )) break;
1748 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1749 read_skip( reader, skip );
1750 len += skip;
1753 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1754 text = (WS_XML_TEXT_NODE *)node;
1755 if (!(utf8 = alloc_utf8_text( start, len )))
1757 heap_free( node );
1758 return E_OUTOFMEMORY;
1760 text->text = &utf8->text;
1762 read_insert_node( reader, reader->current, node );
1763 reader->state = READER_STATE_CDATA;
1764 return S_OK;
1767 static HRESULT read_endcdata( struct reader *reader )
1769 struct node *parent;
1771 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
1772 read_skip( reader, 3 );
1774 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT) parent = reader->current->parent;
1775 else parent = reader->current;
1777 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
1778 reader->last = reader->current;
1779 reader->state = READER_STATE_ENDCDATA;
1780 return S_OK;
1783 static HRESULT read_node( struct reader *reader )
1785 HRESULT hr;
1787 for (;;)
1789 if (read_end_of_data( reader ))
1791 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1792 reader->last = reader->current;
1793 reader->state = READER_STATE_EOF;
1794 return S_OK;
1796 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
1797 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
1798 else if (!read_cmp( reader, "<?", 2 ))
1800 hr = read_xmldecl( reader );
1801 if (FAILED( hr )) return hr;
1803 else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
1804 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
1805 else if (!read_cmp( reader, "<!--", 4 )) return read_comment( reader );
1806 else if (!read_cmp( reader, "<", 1 )) return read_element( reader );
1807 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement( reader );
1808 else return read_text( reader );
1812 /**************************************************************************
1813 * WsReadEndElement [webservices.@]
1815 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
1817 struct reader *reader = (struct reader *)handle;
1819 TRACE( "%p %p\n", handle, error );
1820 if (error) FIXME( "ignoring error parameter\n" );
1822 if (!reader) return E_INVALIDARG;
1823 return read_endelement( reader );
1826 /**************************************************************************
1827 * WsReadNode [webservices.@]
1829 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
1831 struct reader *reader = (struct reader *)handle;
1833 TRACE( "%p %p\n", handle, error );
1834 if (error) FIXME( "ignoring error parameter\n" );
1836 if (!reader) return E_INVALIDARG;
1837 return read_node( reader );
1840 /**************************************************************************
1841 * WsReadStartElement [webservices.@]
1843 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
1845 struct reader *reader = (struct reader *)handle;
1847 TRACE( "%p %p\n", handle, error );
1848 if (error) FIXME( "ignoring error parameter\n" );
1850 if (!reader) return E_INVALIDARG;
1851 return read_startelement( reader );
1854 /**************************************************************************
1855 * WsReadToStartElement [webservices.@]
1857 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
1858 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
1860 struct reader *reader = (struct reader *)handle;
1862 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
1863 if (error) FIXME( "ignoring error parameter\n" );
1865 if (!reader) return E_INVALIDARG;
1866 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
1868 return read_to_startelement( reader, found );
1871 BOOL move_to_root_element( struct node *root, struct node **current )
1873 struct list *ptr;
1874 struct node *node;
1876 if (!(ptr = list_head( &root->children ))) return FALSE;
1877 node = LIST_ENTRY( ptr, struct node, entry );
1878 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1880 *current = node;
1881 return TRUE;
1883 while ((ptr = list_next( &root->children, &node->entry )))
1885 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1886 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1888 *current = next;
1889 return TRUE;
1891 node = next;
1893 return FALSE;
1896 BOOL move_to_next_element( struct node **current )
1898 struct list *ptr;
1899 struct node *node = *current, *parent = (*current)->parent;
1901 if (!parent) return FALSE;
1902 while ((ptr = list_next( &parent->children, &node->entry )))
1904 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1905 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1907 *current = next;
1908 return TRUE;
1910 node = next;
1912 return FALSE;
1915 BOOL move_to_prev_element( struct node **current )
1917 struct list *ptr;
1918 struct node *node = *current, *parent = (*current)->parent;
1920 if (!parent) return FALSE;
1921 while ((ptr = list_prev( &parent->children, &node->entry )))
1923 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
1924 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
1926 *current = prev;
1927 return TRUE;
1929 node = prev;
1931 return FALSE;
1934 BOOL move_to_child_element( struct node **current )
1936 struct list *ptr;
1937 struct node *child, *node = *current;
1939 if (!(ptr = list_head( &node->children ))) return FALSE;
1940 child = LIST_ENTRY( ptr, struct node, entry );
1941 if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
1943 *current = child;
1944 return TRUE;
1946 while ((ptr = list_next( &node->children, &child->entry )))
1948 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1949 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1951 *current = next;
1952 return TRUE;
1954 child = next;
1956 return FALSE;
1959 BOOL move_to_end_element( struct node **current )
1961 struct list *ptr;
1962 struct node *node = *current;
1964 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
1966 if ((ptr = list_tail( &node->children )))
1968 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
1969 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
1971 *current = tail;
1972 return TRUE;
1975 return FALSE;
1978 BOOL move_to_parent_element( struct node **current )
1980 struct node *parent = (*current)->parent;
1982 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
1983 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
1985 *current = parent;
1986 return TRUE;
1988 return FALSE;
1991 BOOL move_to_first_node( struct node **current )
1993 struct list *ptr;
1994 struct node *node = *current;
1996 if ((ptr = list_head( &node->parent->children )))
1998 *current = LIST_ENTRY( ptr, struct node, entry );
1999 return TRUE;
2001 return FALSE;
2004 BOOL move_to_next_node( struct node **current )
2006 struct list *ptr;
2007 struct node *node = *current;
2009 if ((ptr = list_next( &node->parent->children, &node->entry )))
2011 *current = LIST_ENTRY( ptr, struct node, entry );
2012 return TRUE;
2014 return FALSE;
2017 BOOL move_to_prev_node( struct node **current )
2019 struct list *ptr;
2020 struct node *node = *current;
2022 if ((ptr = list_prev( &node->parent->children, &node->entry )))
2024 *current = LIST_ENTRY( ptr, struct node, entry );
2025 return TRUE;
2027 return FALSE;
2030 BOOL move_to_bof( struct node *root, struct node **current )
2032 *current = root;
2033 return TRUE;
2036 BOOL move_to_eof( struct node *root, struct node **current )
2038 struct list *ptr;
2039 if ((ptr = list_tail( &root->children )))
2041 *current = LIST_ENTRY( ptr, struct node, entry );
2042 return TRUE;
2044 return FALSE;
2047 BOOL move_to_child_node( struct node **current )
2049 struct list *ptr;
2050 struct node *node = *current;
2052 if ((ptr = list_head( &node->children )))
2054 *current = LIST_ENTRY( ptr, struct node, entry );
2055 return TRUE;
2057 return FALSE;
2060 BOOL move_to_parent_node( struct node **current )
2062 struct node *parent = (*current)->parent;
2063 if (!parent) return FALSE;
2064 *current = parent;
2065 return TRUE;
2068 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
2070 BOOL success = FALSE;
2071 HRESULT hr = S_OK;
2073 if (!read_end_of_data( reader ))
2075 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
2076 if (hr != S_OK) return hr;
2078 switch (move)
2080 case WS_MOVE_TO_ROOT_ELEMENT:
2081 success = move_to_root_element( reader->root, &reader->current );
2082 break;
2084 case WS_MOVE_TO_NEXT_ELEMENT:
2085 success = move_to_next_element( &reader->current );
2086 break;
2088 case WS_MOVE_TO_PREVIOUS_ELEMENT:
2089 success = move_to_prev_element( &reader->current );
2090 break;
2092 case WS_MOVE_TO_CHILD_ELEMENT:
2093 success = move_to_child_element( &reader->current );
2094 break;
2096 case WS_MOVE_TO_END_ELEMENT:
2097 success = move_to_end_element( &reader->current );
2098 break;
2100 case WS_MOVE_TO_PARENT_ELEMENT:
2101 success = move_to_parent_element( &reader->current );
2102 break;
2104 case WS_MOVE_TO_FIRST_NODE:
2105 success = move_to_first_node( &reader->current );
2106 break;
2108 case WS_MOVE_TO_NEXT_NODE:
2109 success = move_to_next_node( &reader->current );
2110 break;
2112 case WS_MOVE_TO_PREVIOUS_NODE:
2113 success = move_to_prev_node( &reader->current );
2114 break;
2116 case WS_MOVE_TO_CHILD_NODE:
2117 success = move_to_child_node( &reader->current );
2118 break;
2120 case WS_MOVE_TO_BOF:
2121 success = move_to_bof( reader->root, &reader->current );
2122 break;
2124 case WS_MOVE_TO_EOF:
2125 success = move_to_eof( reader->root, &reader->current );
2126 break;
2128 default:
2129 FIXME( "unhandled move %u\n", move );
2130 return E_NOTIMPL;
2133 if (found)
2135 *found = success;
2136 return S_OK;
2138 return success ? S_OK : WS_E_INVALID_FORMAT;
2141 /**************************************************************************
2142 * WsMoveReader [webservices.@]
2144 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
2146 struct reader *reader = (struct reader *)handle;
2148 TRACE( "%p %u %p %p\n", handle, move, found, error );
2149 if (error) FIXME( "ignoring error parameter\n" );
2151 if (!reader) return E_INVALIDARG;
2152 if (!reader->input_type) return WS_E_INVALID_OPERATION;
2154 return read_move_to( reader, move, found );
2157 /**************************************************************************
2158 * WsReadStartAttribute [webservices.@]
2160 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
2162 struct reader *reader = (struct reader *)handle;
2163 WS_XML_ELEMENT_NODE *elem;
2165 TRACE( "%p %u %p\n", handle, index, error );
2166 if (error) FIXME( "ignoring error parameter\n" );
2168 if (!reader) return E_INVALIDARG;
2170 elem = &reader->current->hdr;
2171 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
2172 return WS_E_INVALID_FORMAT;
2174 reader->current_attr = index;
2175 reader->state = READER_STATE_STARTATTRIBUTE;
2176 return S_OK;
2179 /**************************************************************************
2180 * WsReadEndAttribute [webservices.@]
2182 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
2184 struct reader *reader = (struct reader *)handle;
2186 TRACE( "%p %p\n", handle, error );
2187 if (error) FIXME( "ignoring error parameter\n" );
2189 if (!reader) return E_INVALIDARG;
2191 if (reader->state != READER_STATE_STARTATTRIBUTE)
2192 return WS_E_INVALID_FORMAT;
2194 reader->state = READER_STATE_STARTELEMENT;
2195 return S_OK;
2198 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
2200 WCHAR *ret;
2202 switch (text->textType)
2204 case WS_XML_TEXT_TYPE_UTF8:
2206 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
2207 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
2208 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
2209 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
2210 ret[len] = 0;
2211 break;
2213 default:
2214 FIXME( "unhandled type %u\n", text->textType );
2215 return NULL;
2218 return ret;
2221 #define MAX_INT8 0x7f
2222 #define MIN_INT8 (-MAX_INT8 - 1)
2223 #define MAX_INT16 0x7fff
2224 #define MIN_INT16 (-MAX_INT16 - 1)
2225 #define MAX_INT32 0x7fffffff
2226 #define MIN_INT32 (-MAX_INT32 - 1)
2227 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
2228 #define MIN_INT64 (-MAX_INT64 - 1)
2229 #define MAX_UINT8 0xff
2230 #define MAX_UINT16 0xffff
2231 #define MAX_UINT32 0xffffffff
2232 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
2234 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
2236 BOOL negative = FALSE;
2237 const unsigned char *ptr = str;
2239 *ret = 0;
2240 while (len && read_isspace( *ptr )) { ptr++; len--; }
2241 while (len && read_isspace( ptr[len - 1] )) { len--; }
2242 if (!len) return WS_E_INVALID_FORMAT;
2244 if (*ptr == '-')
2246 negative = TRUE;
2247 ptr++;
2248 len--;
2250 if (!len) return WS_E_INVALID_FORMAT;
2252 while (len--)
2254 int val;
2256 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
2257 val = *ptr - '0';
2258 if (negative) val = -val;
2260 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
2261 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
2263 return WS_E_NUMERIC_OVERFLOW;
2265 *ret = *ret * 10 + val;
2266 ptr++;
2269 return S_OK;
2272 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
2274 const unsigned char *ptr = str;
2276 *ret = 0;
2277 while (len && read_isspace( *ptr )) { ptr++; len--; }
2278 while (len && read_isspace( ptr[len - 1] )) { len--; }
2279 if (!len) return WS_E_INVALID_FORMAT;
2281 while (len--)
2283 unsigned int val;
2285 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
2286 val = *ptr - '0';
2288 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
2289 *ret = *ret * 10 + val;
2290 ptr++;
2293 return S_OK;
2296 #if defined(__i386__) || defined(__x86_64__)
2298 #define RC_DOWN 0x100;
2299 BOOL set_fp_rounding( unsigned short *save )
2301 #ifdef __GNUC__
2302 unsigned short fpword;
2304 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
2305 *save = fpword;
2306 fpword |= RC_DOWN;
2307 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
2308 return TRUE;
2309 #else
2310 FIXME( "not implemented\n" );
2311 return FALSE;
2312 #endif
2314 void restore_fp_rounding( unsigned short fpword )
2316 #ifdef __GNUC__
2317 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
2318 #else
2319 FIXME( "not implemented\n" );
2320 #endif
2322 #else
2323 BOOL set_fp_rounding( unsigned short *save )
2325 FIXME( "not implemented\n" );
2326 return FALSE;
2328 void restore_fp_rounding( unsigned short fpword )
2330 FIXME( "not implemented\n" );
2332 #endif
2334 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
2336 static const unsigned __int64 nan = 0xfff8000000000000;
2337 static const unsigned __int64 inf = 0x7ff0000000000000;
2338 static const unsigned __int64 inf_min = 0xfff0000000000000;
2339 HRESULT hr = WS_E_INVALID_FORMAT;
2340 const unsigned char *p = str, *q;
2341 int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
2342 unsigned __int64 val = 0, tmp;
2343 long double exp_val = 1.0, exp_mul = 10.0;
2344 unsigned short fpword;
2346 while (len && read_isspace( *p )) { p++; len--; }
2347 while (len && read_isspace( p[len - 1] )) { len--; }
2348 if (!len) return WS_E_INVALID_FORMAT;
2350 if (len == 3 && !memcmp( p, "NaN", 3 ))
2352 *(unsigned __int64 *)ret = nan;
2353 return S_OK;
2355 else if (len == 3 && !memcmp( p, "INF", 3 ))
2357 *(unsigned __int64 *)ret = inf;
2358 return S_OK;
2360 else if (len == 4 && !memcmp( p, "-INF", 4 ))
2362 *(unsigned __int64 *)ret = inf_min;
2363 return S_OK;
2366 *ret = 0.0;
2367 if (*p == '-')
2369 sign = -1;
2370 p++; len--;
2372 else if (*p == '+') { p++; len--; };
2373 if (!len) return S_OK;
2375 if (!set_fp_rounding( &fpword )) return E_NOTIMPL;
2377 q = p;
2378 while (len && isdigit( *q )) { q++; len--; }
2379 have_digits = nb_digits = q - p;
2380 for (i = 0; i < nb_digits; i++)
2382 tmp = val * 10 + p[i] - '0';
2383 if (val > MAX_UINT64 / 10 || tmp < val)
2385 for (; i < nb_digits; i++) exp++;
2386 break;
2388 val = tmp;
2391 if (len)
2393 if (*q == '.')
2395 p = ++q; len--;
2396 while (len && isdigit( *q )) { q++; len--; };
2397 have_digits |= nb_digits = q - p;
2398 for (i = 0; i < nb_digits; i++)
2400 tmp = val * 10 + p[i] - '0';
2401 if (val > MAX_UINT64 / 10 || tmp < val) break;
2402 val = tmp;
2403 exp--;
2406 if (len > 1 && tolower(*q) == 'e')
2408 if (!have_digits) goto done;
2409 p = ++q; len--;
2410 if (*p == '-')
2412 exp_sign = -1;
2413 p++; len--;
2415 else if (*p == '+') { p++; len--; };
2417 q = p;
2418 while (len && isdigit( *q )) { q++; len--; };
2419 nb_digits = q - p;
2420 if (!nb_digits || len) goto done;
2421 for (i = 0; i < nb_digits; i++)
2423 if (exp_tmp > MAX_INT32 / 10 || (exp_tmp = exp_tmp * 10 + p[i] - '0') < 0)
2424 exp_tmp = MAX_INT32;
2426 exp_tmp *= exp_sign;
2428 if (exp < 0 && exp_tmp < 0 && exp + exp_tmp >= 0) exp = MIN_INT32;
2429 else if (exp > 0 && exp_tmp > 0 && exp + exp_tmp < 0) exp = MAX_INT32;
2430 else exp += exp_tmp;
2433 if (!have_digits || len) goto done;
2435 if ((neg_exp = exp < 0)) exp = -exp;
2436 for (; exp; exp >>= 1)
2438 if (exp & 1) exp_val *= exp_mul;
2439 exp_mul *= exp_mul;
2442 *ret = sign * (neg_exp ? val / exp_val : val * exp_val);
2443 hr = S_OK;
2445 done:
2446 restore_fp_rounding( fpword );
2447 return hr;
2450 static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
2452 static const unsigned char hex[] =
2454 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
2455 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
2456 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
2457 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
2458 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
2459 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
2460 0,10,11,12,13,14,15 /* 0x60 */
2462 const unsigned char *p = str;
2463 ULONG i;
2465 while (len && read_isspace( *p )) { p++; len--; }
2466 while (len && read_isspace( p[len - 1] )) { len--; }
2467 if (len != 36) return WS_E_INVALID_FORMAT;
2469 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
2470 return WS_E_INVALID_FORMAT;
2472 for (i = 0; i < 36; i++)
2474 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
2475 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
2478 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
2479 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
2481 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
2482 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
2484 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
2485 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
2486 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
2487 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
2488 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
2489 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
2490 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
2491 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
2493 return S_OK;
2496 static inline unsigned char decode_char( unsigned char c )
2498 if (c >= 'A' && c <= 'Z') return c - 'A';
2499 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
2500 if (c >= '0' && c <= '9') return c - '0' + 52;
2501 if (c == '+') return 62;
2502 if (c == '/') return 63;
2503 return 64;
2506 static ULONG decode_base64( const unsigned char *base64, ULONG len, unsigned char *buf )
2508 ULONG i = 0;
2509 unsigned char c0, c1, c2, c3;
2510 const unsigned char *p = base64;
2512 while (len > 4)
2514 if ((c0 = decode_char( p[0] )) > 63) return 0;
2515 if ((c1 = decode_char( p[1] )) > 63) return 0;
2516 if ((c2 = decode_char( p[2] )) > 63) return 0;
2517 if ((c3 = decode_char( p[3] )) > 63) return 0;
2518 buf[i + 0] = (c0 << 2) | (c1 >> 4);
2519 buf[i + 1] = (c1 << 4) | (c2 >> 2);
2520 buf[i + 2] = (c2 << 6) | c3;
2521 len -= 4;
2522 i += 3;
2523 p += 4;
2525 if (p[2] == '=')
2527 if ((c0 = decode_char( p[0] )) > 63) return 0;
2528 if ((c1 = decode_char( p[1] )) > 63) return 0;
2529 buf[i] = (c0 << 2) | (c1 >> 4);
2530 i++;
2532 else if (p[3] == '=')
2534 if ((c0 = decode_char( p[0] )) > 63) return 0;
2535 if ((c1 = decode_char( p[1] )) > 63) return 0;
2536 if ((c2 = decode_char( p[2] )) > 63) return 0;
2537 buf[i + 0] = (c0 << 2) | (c1 >> 4);
2538 buf[i + 1] = (c1 << 4) | (c2 >> 2);
2539 i += 2;
2541 else
2543 if ((c0 = decode_char( p[0] )) > 63) return 0;
2544 if ((c1 = decode_char( p[1] )) > 63) return 0;
2545 if ((c2 = decode_char( p[2] )) > 63) return 0;
2546 if ((c3 = decode_char( p[3] )) > 63) return 0;
2547 buf[i + 0] = (c0 << 2) | (c1 >> 4);
2548 buf[i + 1] = (c1 << 4) | (c2 >> 2);
2549 buf[i + 2] = (c2 << 6) | c3;
2550 i += 3;
2552 return i;
2555 static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_BYTES *ret )
2557 const unsigned char *p = str;
2559 while (len && read_isspace( *p )) { p++; len--; }
2560 while (len && read_isspace( p[len - 1] )) { len--; }
2562 if (len % 4) return WS_E_INVALID_FORMAT;
2563 if (!(ret->bytes = ws_alloc( heap, len * 3 / 4 ))) return WS_E_QUOTA_EXCEEDED;
2564 ret->length = decode_base64( p, len, ret->bytes );
2565 return S_OK;
2568 static const int month_offsets[2][12] =
2570 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
2571 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
2574 static inline int valid_day( int year, int month, int day )
2576 return day > 0 && day <= month_days[leap_year( year )][month - 1];
2579 static inline int leap_days_before( int year )
2581 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
2584 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
2586 const unsigned char *p = bytes, *q;
2587 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
2589 while (len && read_isspace( *p )) { p++; len--; }
2590 while (len && read_isspace( p[len - 1] )) { len--; }
2592 q = p;
2593 while (len && isdigit( *q )) { q++; len--; };
2594 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
2595 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
2596 if (year < 1) return WS_E_INVALID_FORMAT;
2598 p = ++q; len--;
2599 while (len && isdigit( *q )) { q++; len--; };
2600 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
2601 month = (p[0] - '0') * 10 + p[1] - '0';
2602 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
2604 p = ++q; len--;
2605 while (len && isdigit( *q )) { q++; len--; };
2606 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
2607 day = (p[0] - '0') * 10 + p[1] - '0';
2608 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
2610 p = ++q; len--;
2611 while (len && isdigit( *q )) { q++; len--; };
2612 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2613 hour = (p[0] - '0') * 10 + p[1] - '0';
2614 if (hour > 24) return WS_E_INVALID_FORMAT;
2616 p = ++q; len--;
2617 while (len && isdigit( *q )) { q++; len--; };
2618 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2619 min = (p[0] - '0') * 10 + p[1] - '0';
2620 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
2622 p = ++q; len--;
2623 while (len && isdigit( *q )) { q++; len--; };
2624 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
2625 sec = (p[0] - '0') * 10 + p[1] - '0';
2626 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
2628 if (*q == '.')
2630 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
2631 p = ++q; len--;
2632 while (len && isdigit( *q )) { q++; len--; };
2633 nb_digits = q - p;
2634 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
2635 for (i = 0; i < nb_digits; i++)
2637 sec_frac += (p[i] - '0') * mul;
2638 mul /= 10;
2641 if (*q == 'Z')
2643 if (--len) return WS_E_INVALID_FORMAT;
2644 tz_hour = tz_min = tz_neg = 0;
2645 ret->format = WS_DATETIME_FORMAT_UTC;
2647 else if (*q == '+' || *q == '-')
2649 tz_neg = (*q == '-') ? 1 : 0;
2651 p = ++q; len--;
2652 while (len && isdigit( *q )) { q++; len--; };
2653 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2654 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
2655 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
2657 p = ++q; len--;
2658 while (len && isdigit( *q )) { q++; len--; };
2659 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
2660 tz_min = (p[0] - '0') * 10 + p[1] - '0';
2661 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
2663 ret->format = WS_DATETIME_FORMAT_LOCAL;
2665 else return WS_E_INVALID_FORMAT;
2667 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
2668 ret->ticks += month_offsets[leap_year( year )][month - 1] * TICKS_PER_DAY;
2669 ret->ticks += (day - 1) * TICKS_PER_DAY;
2670 ret->ticks += hour * TICKS_PER_HOUR;
2671 ret->ticks += min * TICKS_PER_MIN;
2672 ret->ticks += sec * TICKS_PER_SEC;
2673 ret->ticks += sec_frac;
2675 if (tz_neg)
2677 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
2678 return WS_E_INVALID_FORMAT;
2679 ret->ticks += tz_hour * TICKS_PER_HOUR;
2680 ret->ticks += tz_min * TICKS_PER_MIN;
2682 else
2684 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
2685 return WS_E_INVALID_FORMAT;
2686 ret->ticks -= tz_hour * TICKS_PER_HOUR;
2687 ret->ticks -= tz_min * TICKS_PER_MIN;
2690 return S_OK;
2693 /**************************************************************************
2694 * WsDateTimeToFileTime [webservices.@]
2696 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
2698 unsigned __int64 ticks;
2700 TRACE( "%p %p %p\n", dt, ft, error );
2701 if (error) FIXME( "ignoring error parameter\n" );
2703 if (!dt || !ft) return E_INVALIDARG;
2705 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
2706 ticks = dt->ticks - TICKS_1601_01_01;
2707 ft->dwHighDateTime = ticks >> 32;
2708 ft->dwLowDateTime = (DWORD)ticks;
2709 return S_OK;
2712 /**************************************************************************
2713 * WsFileTimeToDateTime [webservices.@]
2715 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
2717 unsigned __int64 ticks;
2719 TRACE( "%p %p %p\n", ft, dt, error );
2720 if (error) FIXME( "ignoring error parameter\n" );
2722 if (!dt || !ft) return E_INVALIDARG;
2724 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
2725 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
2726 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
2727 dt->ticks = ticks + TICKS_1601_01_01;
2728 dt->format = WS_DATETIME_FORMAT_UTC;
2729 return S_OK;
2732 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
2734 WS_XML_TEXT_NODE *text;
2736 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
2737 return WS_E_INVALID_FORMAT;
2739 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
2740 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
2742 FIXME( "text type %u not supported\n", text->text->textType );
2743 return E_NOTIMPL;
2745 *ret = (WS_XML_UTF8_TEXT *)text->text;
2746 return S_OK;
2749 static HRESULT read_get_attribute_text( struct reader *reader, ULONG index, WS_XML_UTF8_TEXT **ret )
2751 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2752 WS_XML_ATTRIBUTE *attr;
2754 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
2755 return WS_E_INVALID_FORMAT;
2757 attr = elem->attributes[index];
2758 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
2760 FIXME( "text type %u not supported\n", attr->value->textType );
2761 return E_NOTIMPL;
2763 *ret = (WS_XML_UTF8_TEXT *)attr->value;
2764 return S_OK;
2767 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
2768 const WS_XML_STRING *ns, ULONG *index )
2770 ULONG i;
2771 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2773 if (!localname)
2775 *index = reader->current_attr;
2776 return TRUE;
2778 for (i = 0; i < elem->attributeCount; i++)
2780 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
2781 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
2783 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
2784 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
2786 *index = i;
2787 return TRUE;
2790 return FALSE;
2793 /**************************************************************************
2794 * WsFindAttribute [webservices.@]
2796 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
2797 const WS_XML_STRING *ns, BOOL required, ULONG *index,
2798 WS_ERROR *error )
2800 struct reader *reader = (struct reader *)handle;
2802 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
2803 required, index, error );
2804 if (error) FIXME( "ignoring error parameter\n" );
2806 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
2808 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
2809 return WS_E_INVALID_OPERATION;
2811 if (!find_attribute( reader, localname, ns, index ))
2813 if (required) return WS_E_INVALID_FORMAT;
2814 *index = ~0u;
2815 return S_FALSE;
2817 return S_OK;
2820 static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
2821 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2822 WS_XML_UTF8_TEXT **ret, BOOL *found )
2824 switch (mapping)
2826 case WS_ATTRIBUTE_TYPE_MAPPING:
2828 ULONG index;
2829 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
2830 return read_get_attribute_text( reader, index, ret );
2832 case WS_ELEMENT_TYPE_MAPPING:
2833 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2834 case WS_ANY_ELEMENT_TYPE_MAPPING:
2836 HRESULT hr;
2837 *found = TRUE;
2838 if (localname)
2840 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2842 if (WsXmlStringEquals( localname, elem->localName, NULL ) != S_OK ||
2843 WsXmlStringEquals( ns, elem->ns, NULL ) != S_OK)
2845 *found = FALSE;
2846 return S_OK;
2848 if ((hr = read_startelement( reader )) != S_OK) return hr;
2850 return read_get_node_text( reader, ret );
2852 default:
2853 FIXME( "mapping %u not supported\n", mapping );
2854 return E_NOTIMPL;
2858 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
2859 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2860 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
2861 WS_HEAP *heap, void *ret, ULONG size )
2863 WS_XML_UTF8_TEXT *utf8;
2864 HRESULT hr;
2865 BOOL found, val = FALSE;
2867 if (desc)
2869 FIXME( "description not supported\n" );
2870 return E_NOTIMPL;
2872 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2873 if (found)
2875 ULONG len = utf8->value.length;
2876 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
2877 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
2878 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
2879 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
2880 else return WS_E_INVALID_FORMAT;
2883 switch (option)
2885 case WS_READ_REQUIRED_VALUE:
2886 if (!found) return WS_E_INVALID_FORMAT;
2887 /* fall through */
2889 case WS_READ_NILLABLE_VALUE:
2890 if (size != sizeof(BOOL)) return E_INVALIDARG;
2891 *(BOOL *)ret = val;
2892 break;
2894 case WS_READ_REQUIRED_POINTER:
2895 if (!found) return WS_E_INVALID_FORMAT;
2896 /* fall through */
2898 case WS_READ_OPTIONAL_POINTER:
2899 case WS_READ_NILLABLE_POINTER:
2901 BOOL *heap_val = NULL;
2902 if (size != sizeof(heap_val)) return E_INVALIDARG;
2903 if (found)
2905 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2906 *heap_val = val;
2908 *(BOOL **)ret = heap_val;
2909 break;
2911 default:
2912 FIXME( "read option %u not supported\n", option );
2913 return E_NOTIMPL;
2916 return S_OK;
2919 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
2920 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2921 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
2922 WS_HEAP *heap, void *ret, ULONG size )
2924 WS_XML_UTF8_TEXT *utf8;
2925 HRESULT hr;
2926 INT64 val = 0;
2927 BOOL found;
2929 if (desc)
2931 FIXME( "description not supported\n" );
2932 return E_NOTIMPL;
2934 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2935 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
2936 return hr;
2938 switch (option)
2940 case WS_READ_REQUIRED_VALUE:
2941 if (!found) return WS_E_INVALID_FORMAT;
2942 /* fall through */
2944 case WS_READ_NILLABLE_VALUE:
2945 if (size != sizeof(INT8)) return E_INVALIDARG;
2946 *(INT8 *)ret = val;
2947 break;
2949 case WS_READ_REQUIRED_POINTER:
2950 if (!found) return WS_E_INVALID_FORMAT;
2951 /* fall through */
2953 case WS_READ_OPTIONAL_POINTER:
2954 case WS_READ_NILLABLE_POINTER:
2956 INT8 *heap_val = NULL;
2957 if (size != sizeof(heap_val)) return E_INVALIDARG;
2958 if (found)
2960 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2961 *heap_val = val;
2963 *(INT8 **)ret = heap_val;
2964 break;
2966 default:
2967 FIXME( "read option %u not supported\n", option );
2968 return E_NOTIMPL;
2971 return S_OK;
2974 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
2975 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2976 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
2977 WS_HEAP *heap, void *ret, ULONG size )
2979 WS_XML_UTF8_TEXT *utf8;
2980 HRESULT hr;
2981 INT64 val = 0;
2982 BOOL found;
2984 if (desc)
2986 FIXME( "description not supported\n" );
2987 return E_NOTIMPL;
2989 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2990 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
2991 return hr;
2993 switch (option)
2995 case WS_READ_REQUIRED_VALUE:
2996 if (!found) return WS_E_INVALID_FORMAT;
2997 /* fall through */
2999 case WS_READ_NILLABLE_VALUE:
3000 if (size != sizeof(INT16)) return E_INVALIDARG;
3001 *(INT16 *)ret = val;
3002 break;
3004 case WS_READ_REQUIRED_POINTER:
3005 if (!found) return WS_E_INVALID_FORMAT;
3006 /* fall through */
3008 case WS_READ_OPTIONAL_POINTER:
3009 case WS_READ_NILLABLE_POINTER:
3011 INT16 *heap_val = NULL;
3012 if (size != sizeof(heap_val)) return E_INVALIDARG;
3013 if (found)
3015 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3016 *heap_val = val;
3018 *(INT16 **)ret = heap_val;
3019 break;
3021 default:
3022 FIXME( "read option %u not supported\n", option );
3023 return E_NOTIMPL;
3026 return S_OK;
3029 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
3030 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3031 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
3032 WS_HEAP *heap, void *ret, ULONG size )
3034 WS_XML_UTF8_TEXT *utf8;
3035 HRESULT hr;
3036 INT64 val = 0;
3037 BOOL found;
3039 if (desc)
3041 FIXME( "description not supported\n" );
3042 return E_NOTIMPL;
3044 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3045 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
3046 return hr;
3048 switch (option)
3050 case WS_READ_REQUIRED_VALUE:
3051 if (!found) return WS_E_INVALID_FORMAT;
3052 /* fall through */
3054 case WS_READ_NILLABLE_VALUE:
3055 if (size != sizeof(INT32)) return E_INVALIDARG;
3056 *(INT32 *)ret = val;
3057 break;
3059 case WS_READ_REQUIRED_POINTER:
3060 if (!found) return WS_E_INVALID_FORMAT;
3061 /* fall through */
3063 case WS_READ_OPTIONAL_POINTER:
3064 case WS_READ_NILLABLE_POINTER:
3066 INT32 *heap_val = NULL;
3067 if (size != sizeof(heap_val)) return E_INVALIDARG;
3068 if (found)
3070 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3071 *heap_val = val;
3073 *(INT32 **)ret = heap_val;
3074 break;
3076 default:
3077 FIXME( "read option %u not supported\n", option );
3078 return E_NOTIMPL;
3081 return S_OK;
3084 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
3085 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3086 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
3087 WS_HEAP *heap, void *ret, ULONG size )
3089 WS_XML_UTF8_TEXT *utf8;
3090 HRESULT hr;
3091 INT64 val = 0;
3092 BOOL found;
3094 if (desc)
3096 FIXME( "description not supported\n" );
3097 return E_NOTIMPL;
3099 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3100 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
3101 return hr;
3103 switch (option)
3105 case WS_READ_REQUIRED_VALUE:
3106 if (!found) return WS_E_INVALID_FORMAT;
3107 /* fall through */
3109 case WS_READ_NILLABLE_VALUE:
3110 if (size != sizeof(INT64)) return E_INVALIDARG;
3111 *(INT64 *)ret = val;
3112 break;
3114 case WS_READ_REQUIRED_POINTER:
3115 if (!found) return WS_E_INVALID_FORMAT;
3116 /* fall through */
3118 case WS_READ_OPTIONAL_POINTER:
3119 case WS_READ_NILLABLE_POINTER:
3121 INT64 *heap_val = NULL;
3122 if (size != sizeof(heap_val)) return E_INVALIDARG;
3123 if (found)
3125 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3126 *heap_val = val;
3128 *(INT64 **)ret = heap_val;
3129 break;
3131 default:
3132 FIXME( "read option %u not supported\n", option );
3133 return E_NOTIMPL;
3136 return S_OK;
3139 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
3140 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3141 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
3142 WS_HEAP *heap, void *ret, ULONG size )
3144 WS_XML_UTF8_TEXT *utf8;
3145 HRESULT hr;
3146 UINT64 val = 0;
3147 BOOL found;
3149 if (desc)
3151 FIXME( "description not supported\n" );
3152 return E_NOTIMPL;
3154 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3155 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
3156 return hr;
3158 switch (option)
3160 case WS_READ_REQUIRED_VALUE:
3161 if (!found) return WS_E_INVALID_FORMAT;
3162 /* fall through */
3164 case WS_READ_NILLABLE_VALUE:
3165 if (size != sizeof(UINT8)) return E_INVALIDARG;
3166 *(UINT8 *)ret = val;
3167 break;
3169 case WS_READ_REQUIRED_POINTER:
3170 if (!found) return WS_E_INVALID_FORMAT;
3171 /* fall through */
3173 case WS_READ_OPTIONAL_POINTER:
3174 case WS_READ_NILLABLE_POINTER:
3176 UINT8 *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 *(UINT8 **)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_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
3195 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3196 const WS_UINT16_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 = 0;
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_UINT16, &val )) != S_OK)
3211 return hr;
3213 switch (option)
3215 case WS_READ_REQUIRED_VALUE:
3216 if (!found) return WS_E_INVALID_FORMAT;
3217 /* fall through */
3219 case WS_READ_NILLABLE_VALUE:
3220 if (size != sizeof(UINT16)) return E_INVALIDARG;
3221 *(UINT16 *)ret = val;
3222 break;
3224 case WS_READ_REQUIRED_POINTER:
3225 if (!found) return WS_E_INVALID_FORMAT;
3226 /* fall through */
3228 case WS_READ_OPTIONAL_POINTER:
3229 case WS_READ_NILLABLE_POINTER:
3231 UINT16 *heap_val = NULL;
3232 if (size != sizeof(heap_val)) return E_INVALIDARG;
3233 if (found)
3235 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3236 *heap_val = val;
3238 *(UINT16 **)ret = heap_val;
3239 break;
3241 default:
3242 FIXME( "read option %u not supported\n", option );
3243 return E_NOTIMPL;
3246 return S_OK;
3249 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
3250 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3251 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
3252 WS_HEAP *heap, void *ret, ULONG size )
3254 WS_XML_UTF8_TEXT *utf8;
3255 HRESULT hr;
3256 UINT64 val = 0;
3257 BOOL found;
3259 if (desc)
3261 FIXME( "description not supported\n" );
3262 return E_NOTIMPL;
3264 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3265 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
3266 return hr;
3268 switch (option)
3270 case WS_READ_REQUIRED_VALUE:
3271 if (!found) return WS_E_INVALID_FORMAT;
3272 /* fall through */
3274 case WS_READ_NILLABLE_VALUE:
3275 if (size != sizeof(UINT32)) return E_INVALIDARG;
3276 *(UINT32 *)ret = val;
3277 break;
3279 case WS_READ_REQUIRED_POINTER:
3280 if (!found) return WS_E_INVALID_FORMAT;
3281 /* fall through */
3283 case WS_READ_OPTIONAL_POINTER:
3284 case WS_READ_NILLABLE_POINTER:
3286 UINT32 *heap_val = NULL;
3287 if (size != sizeof(heap_val)) return E_INVALIDARG;
3288 if (found)
3290 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3291 *heap_val = val;
3293 *(UINT32 **)ret = heap_val;
3294 break;
3296 default:
3297 FIXME( "read option %u not supported\n", option );
3298 return E_NOTIMPL;
3301 return S_OK;
3304 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
3305 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3306 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
3307 WS_HEAP *heap, void *ret, ULONG size )
3309 WS_XML_UTF8_TEXT *utf8;
3310 HRESULT hr;
3311 UINT64 val = 0;
3312 BOOL found;
3314 if (desc)
3316 FIXME( "description not supported\n" );
3317 return E_NOTIMPL;
3319 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3320 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
3321 return hr;
3323 switch (option)
3325 case WS_READ_REQUIRED_VALUE:
3326 if (!found) return WS_E_INVALID_FORMAT;
3327 /* fall through */
3329 case WS_READ_NILLABLE_VALUE:
3330 if (size != sizeof(UINT64)) return E_INVALIDARG;
3331 *(UINT64 *)ret = val;
3332 break;
3334 case WS_READ_REQUIRED_POINTER:
3335 if (!found) return WS_E_INVALID_FORMAT;
3336 /* fall through */
3338 case WS_READ_OPTIONAL_POINTER:
3339 case WS_READ_NILLABLE_POINTER:
3341 UINT64 *heap_val = NULL;
3342 if (size != sizeof(heap_val)) return E_INVALIDARG;
3343 if (found)
3345 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3346 *heap_val = val;
3348 *(UINT64 **)ret = heap_val;
3349 break;
3351 default:
3352 FIXME( "read option %u not supported\n", option );
3353 return E_NOTIMPL;
3356 return S_OK;
3359 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
3360 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3361 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
3362 WS_HEAP *heap, void *ret, ULONG size )
3364 WS_XML_UTF8_TEXT *utf8;
3365 HRESULT hr;
3366 double val = 0.0;
3367 BOOL found;
3369 if (desc) FIXME( "ignoring description\n" );
3371 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3372 if (found && (hr = str_to_double( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
3374 switch (option)
3376 case WS_READ_REQUIRED_VALUE:
3377 if (!found) return WS_E_INVALID_FORMAT;
3378 /* fall through */
3380 case WS_READ_NILLABLE_VALUE:
3381 if (size != sizeof(double)) return E_INVALIDARG;
3382 *(double *)ret = val;
3383 break;
3385 case WS_READ_REQUIRED_POINTER:
3386 if (!found) return WS_E_INVALID_FORMAT;
3387 /* fall through */
3389 case WS_READ_OPTIONAL_POINTER:
3390 case WS_READ_NILLABLE_POINTER:
3392 double *heap_val = NULL;
3393 if (size != sizeof(heap_val)) return E_INVALIDARG;
3394 if (found)
3396 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3397 *heap_val = val;
3399 *(double **)ret = heap_val;
3400 break;
3402 default:
3403 FIXME( "read option %u not supported\n", option );
3404 return E_NOTIMPL;
3407 return S_OK;
3410 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
3411 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3412 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
3413 WS_HEAP *heap, WCHAR **ret, ULONG size )
3415 WS_XML_UTF8_TEXT *utf8;
3416 HRESULT hr;
3417 WCHAR *str = NULL;
3418 BOOL found;
3420 if (desc)
3422 FIXME( "description not supported\n" );
3423 return E_NOTIMPL;
3425 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3426 if (found && !(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
3428 switch (option)
3430 case WS_READ_REQUIRED_POINTER:
3431 if (!found) return WS_E_INVALID_FORMAT;
3432 /* fall through */
3434 case WS_READ_OPTIONAL_POINTER:
3435 case WS_READ_NILLABLE_POINTER:
3436 if (size != sizeof(str)) return E_INVALIDARG;
3437 *ret = str;
3438 break;
3440 default:
3441 FIXME( "read option %u not supported\n", option );
3442 return E_NOTIMPL;
3445 return S_OK;
3448 static HRESULT get_enum_value( const WS_XML_UTF8_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
3450 ULONG i;
3451 for (i = 0; i < desc->valueCount; i++)
3453 if (WsXmlStringEquals( &text->value, desc->values[i].name, NULL ) == S_OK)
3455 *ret = desc->values[i].value;
3456 return S_OK;
3459 return WS_E_INVALID_FORMAT;
3462 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
3463 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3464 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
3465 WS_HEAP *heap, void *ret, ULONG size )
3467 WS_XML_UTF8_TEXT *utf8;
3468 HRESULT hr;
3469 int val = 0;
3470 BOOL found;
3472 if (!desc) return E_INVALIDARG;
3474 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3475 if (found && (hr = get_enum_value( utf8, desc, &val )) != S_OK) return hr;
3477 switch (option)
3479 case WS_READ_REQUIRED_VALUE:
3480 if (!found) return WS_E_INVALID_FORMAT;
3481 /* fall through */
3483 case WS_READ_NILLABLE_VALUE:
3484 if (size != sizeof(int)) return E_INVALIDARG;
3485 *(int *)ret = val;
3486 break;
3488 case WS_READ_REQUIRED_POINTER:
3489 if (!found) return WS_E_INVALID_FORMAT;
3490 /* fall through */
3492 case WS_READ_OPTIONAL_POINTER:
3493 case WS_READ_NILLABLE_POINTER:
3495 int *heap_val = NULL;
3496 if (size != sizeof(heap_val)) return E_INVALIDARG;
3497 if (found)
3499 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3500 *heap_val = val;
3502 *(int **)ret = heap_val;
3503 break;
3505 default:
3506 FIXME( "read option %u not supported\n", option );
3507 return E_NOTIMPL;
3510 return S_OK;
3513 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
3514 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3515 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
3516 WS_HEAP *heap, void *ret, ULONG size )
3518 WS_XML_UTF8_TEXT *utf8;
3519 HRESULT hr;
3520 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
3521 BOOL found;
3523 if (desc) FIXME( "ignoring description\n" );
3525 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3526 if (found && (hr = str_to_datetime( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
3528 switch (option)
3530 case WS_READ_REQUIRED_VALUE:
3531 if (!found) return WS_E_INVALID_FORMAT;
3532 /* fall through */
3534 case WS_READ_NILLABLE_VALUE:
3535 if (size != sizeof(WS_DATETIME)) return E_INVALIDARG;
3536 *(WS_DATETIME *)ret = val;
3537 break;
3539 case WS_READ_REQUIRED_POINTER:
3540 if (!found) return WS_E_INVALID_FORMAT;
3541 /* fall through */
3543 case WS_READ_OPTIONAL_POINTER:
3544 case WS_READ_NILLABLE_POINTER:
3546 WS_DATETIME *heap_val = NULL;
3547 if (size != sizeof(heap_val)) return E_INVALIDARG;
3548 if (found)
3550 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3551 *heap_val = val;
3553 *(WS_DATETIME **)ret = heap_val;
3554 break;
3556 default:
3557 FIXME( "read option %u not supported\n", option );
3558 return E_NOTIMPL;
3561 return S_OK;
3564 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
3565 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3566 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
3567 WS_HEAP *heap, void *ret, ULONG size )
3569 WS_XML_UTF8_TEXT *utf8;
3570 GUID val = {0};
3571 HRESULT hr;
3572 BOOL found;
3574 if (desc) FIXME( "ignoring description\n" );
3576 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3577 if (found && (hr = str_to_guid( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
3579 switch (option)
3581 case WS_READ_REQUIRED_VALUE:
3582 if (!found) return WS_E_INVALID_FORMAT;
3583 /* fall through */
3585 case WS_READ_NILLABLE_VALUE:
3586 if (size != sizeof(GUID)) return E_INVALIDARG;
3587 *(GUID *)ret = val;
3588 break;
3590 case WS_READ_REQUIRED_POINTER:
3591 if (!found) return WS_E_INVALID_FORMAT;
3592 /* fall through */
3594 case WS_READ_OPTIONAL_POINTER:
3595 case WS_READ_NILLABLE_POINTER:
3597 GUID *heap_val = NULL;
3598 if (size != sizeof(heap_val)) return E_INVALIDARG;
3599 if (found)
3601 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3602 *heap_val = val;
3604 *(GUID **)ret = heap_val;
3605 break;
3607 default:
3608 FIXME( "read option %u not supported\n", option );
3609 return E_NOTIMPL;
3612 return S_OK;
3615 static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
3616 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3617 const WS_BYTES_DESCRIPTION *desc, WS_READ_OPTION option,
3618 WS_HEAP *heap, void *ret, ULONG size )
3620 WS_XML_UTF8_TEXT *utf8;
3621 WS_BYTES val = {0};
3622 HRESULT hr;
3623 BOOL found;
3625 if (desc) FIXME( "ignoring description\n" );
3627 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3628 if (found && (hr = str_to_bytes( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
3629 return hr;
3631 switch (option)
3633 case WS_READ_REQUIRED_VALUE:
3634 if (!found) return WS_E_INVALID_FORMAT;
3635 /* fall through */
3637 case WS_READ_NILLABLE_VALUE:
3638 if (size != sizeof(WS_BYTES)) return E_INVALIDARG;
3639 *(WS_BYTES *)ret = val;
3640 break;
3642 case WS_READ_REQUIRED_POINTER:
3643 if (!found) return WS_E_INVALID_FORMAT;
3644 /* fall through */
3646 case WS_READ_OPTIONAL_POINTER:
3647 case WS_READ_NILLABLE_POINTER:
3649 WS_BYTES *heap_val = NULL;
3650 if (size != sizeof(heap_val)) return E_INVALIDARG;
3651 if (found)
3653 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3654 *heap_val = val;
3656 *(WS_BYTES **)ret = heap_val;
3657 break;
3659 default:
3660 FIXME( "read option %u not supported\n", option );
3661 return E_NOTIMPL;
3664 return S_OK;
3667 static BOOL is_empty_text_node( const struct node *node )
3669 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
3670 const WS_XML_UTF8_TEXT *utf8;
3671 ULONG i;
3673 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
3674 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
3676 ERR( "unhandled text type %u\n", text->text->textType );
3677 return FALSE;
3679 utf8 = (const WS_XML_UTF8_TEXT *)text->text;
3680 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
3681 return TRUE;
3684 static HRESULT read_next_node( struct reader *reader )
3686 if (reader->current == reader->last) return read_node( reader );
3687 if (move_to_child_node( &reader->current )) return S_OK;
3688 if (move_to_next_node( &reader->current )) return S_OK;
3689 if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
3690 if (move_to_next_node( &reader->current )) return S_OK;
3691 return WS_E_INVALID_FORMAT;
3694 /* skips comment and empty text nodes */
3695 static HRESULT read_type_next_node( struct reader *reader )
3697 for (;;)
3699 HRESULT hr;
3700 WS_XML_NODE_TYPE type;
3702 if ((hr = read_next_node( reader )) != S_OK) return hr;
3703 type = node_type( reader->current );
3704 if (type == WS_XML_NODE_TYPE_COMMENT ||
3705 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
3706 return S_OK;
3710 static BOOL match_current_element( struct reader *reader, const WS_XML_STRING *localname,
3711 const WS_XML_STRING *ns )
3713 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3714 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3715 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
3716 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
3719 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
3720 const WS_XML_STRING *ns )
3722 struct node *node;
3723 ULONG attr;
3724 HRESULT hr;
3726 if (!localname) return S_OK; /* assume reader is already correctly positioned */
3727 if (reader->current == reader->last)
3729 BOOL found;
3730 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
3731 if (!found) return WS_E_INVALID_FORMAT;
3733 if (match_current_element( reader, localname, ns )) return S_OK;
3735 node = reader->current;
3736 attr = reader->current_attr;
3738 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
3739 if (match_current_element( reader, localname, ns )) return S_OK;
3741 reader->current = node;
3742 reader->current_attr = attr;
3744 return WS_E_INVALID_FORMAT;
3747 ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
3749 switch (type)
3751 case WS_INT8_TYPE:
3752 case WS_UINT8_TYPE:
3753 return sizeof(INT8);
3755 case WS_INT16_TYPE:
3756 case WS_UINT16_TYPE:
3757 return sizeof(INT16);
3759 case WS_BOOL_TYPE:
3760 case WS_INT32_TYPE:
3761 case WS_UINT32_TYPE:
3762 case WS_ENUM_TYPE:
3763 return sizeof(INT32);
3765 case WS_INT64_TYPE:
3766 case WS_UINT64_TYPE:
3767 return sizeof(INT64);
3769 case WS_DOUBLE_TYPE:
3770 return sizeof(double);
3772 case WS_DATETIME_TYPE:
3773 return sizeof(WS_DATETIME);
3775 case WS_GUID_TYPE:
3776 return sizeof(GUID);
3778 case WS_WSZ_TYPE:
3779 return sizeof(WCHAR *);
3781 case WS_BYTES_TYPE:
3782 return sizeof(WS_BYTES);
3784 case WS_STRUCT_TYPE:
3785 return desc->size;
3787 default:
3788 ERR( "unhandled type %u\n", type );
3789 return 0;
3793 static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
3795 if (options & WS_FIELD_POINTER)
3797 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
3798 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
3799 return WS_READ_REQUIRED_POINTER;
3802 switch (type)
3804 case WS_BOOL_TYPE:
3805 case WS_INT8_TYPE:
3806 case WS_INT16_TYPE:
3807 case WS_INT32_TYPE:
3808 case WS_INT64_TYPE:
3809 case WS_UINT8_TYPE:
3810 case WS_UINT16_TYPE:
3811 case WS_UINT32_TYPE:
3812 case WS_UINT64_TYPE:
3813 case WS_DOUBLE_TYPE:
3814 case WS_DATETIME_TYPE:
3815 case WS_GUID_TYPE:
3816 case WS_BYTES_TYPE:
3817 case WS_STRUCT_TYPE:
3818 case WS_ENUM_TYPE:
3819 if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
3820 return WS_READ_REQUIRED_VALUE;
3822 case WS_WSZ_TYPE:
3823 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
3824 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
3825 return WS_READ_REQUIRED_POINTER;
3827 default:
3828 FIXME( "unhandled type %u\n", type );
3829 return 0;
3833 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
3834 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
3835 void *, ULONG );
3837 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3838 WS_HEAP *heap, void **ret, ULONG *count )
3840 HRESULT hr;
3841 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
3842 WS_READ_OPTION option;
3843 char *buf;
3845 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
3847 /* wrapper element */
3848 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
3849 return hr;
3851 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
3852 item_size = get_type_size( desc->type, desc->typeDescription );
3853 else
3854 item_size = sizeof(void *);
3856 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
3857 for (;;)
3859 if (nb_items >= nb_allocated)
3861 if (!(buf = ws_realloc_zero( heap, buf, nb_allocated * 2 * item_size )))
3862 return WS_E_QUOTA_EXCEEDED;
3863 nb_allocated *= 2;
3865 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
3866 desc->typeDescription, option, heap, buf + offset, item_size );
3867 if (hr == WS_E_INVALID_FORMAT) break;
3868 if (hr != S_OK)
3870 ws_free( heap, buf );
3871 return hr;
3873 offset += item_size;
3874 nb_items++;
3877 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
3879 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
3881 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
3882 desc->itemRange->maxItemCount );
3883 ws_free( heap, buf );
3884 return WS_E_INVALID_FORMAT;
3887 *count = nb_items;
3888 *ret = buf;
3890 return S_OK;
3893 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3894 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
3896 HRESULT hr;
3897 if (reader->current == reader->last)
3899 BOOL found;
3900 if ((hr = read_to_startelement( reader, &found )) != S_OK) return S_OK;
3901 if (!found) return WS_E_INVALID_FORMAT;
3903 if ((hr = read_next_node( reader )) != S_OK) return hr;
3904 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
3906 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
3907 desc->typeDescription, option, heap, ret, size );
3910 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3911 WS_HEAP *heap, char *buf )
3913 char *ptr;
3914 WS_READ_OPTION option;
3915 ULONG size;
3916 HRESULT hr;
3918 if (!desc) return E_INVALIDARG;
3919 if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE|WS_FIELD_NILLABLE_ITEM))
3921 FIXME( "options %08x not supported\n", desc->options );
3922 return E_NOTIMPL;
3924 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
3926 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
3927 size = get_type_size( desc->type, desc->typeDescription );
3928 else
3929 size = sizeof(void *);
3931 ptr = buf + desc->offset;
3932 switch (desc->mapping)
3934 case WS_ATTRIBUTE_FIELD_MAPPING:
3935 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
3936 desc->typeDescription, option, heap, ptr, size );
3937 break;
3939 case WS_ELEMENT_FIELD_MAPPING:
3940 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
3941 desc->typeDescription, option, heap, ptr, size );
3942 break;
3944 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
3946 ULONG count;
3947 hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, &count );
3948 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
3949 break;
3951 case WS_TEXT_FIELD_MAPPING:
3952 hr = read_type_text( reader, desc, option, heap, ptr, size );
3953 break;
3955 default:
3956 FIXME( "unhandled field mapping %u\n", desc->mapping );
3957 return E_NOTIMPL;
3960 if (hr == WS_E_INVALID_FORMAT)
3962 switch (option)
3964 case WS_READ_REQUIRED_VALUE:
3965 case WS_READ_REQUIRED_POINTER:
3966 return WS_E_INVALID_FORMAT;
3968 case WS_READ_NILLABLE_VALUE:
3969 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
3970 return S_OK;
3972 case WS_READ_OPTIONAL_POINTER:
3973 case WS_READ_NILLABLE_POINTER:
3974 *(void **)ptr = NULL;
3975 return S_OK;
3977 default:
3978 ERR( "unhandled option %u\n", option );
3979 return E_NOTIMPL;
3983 return hr;
3986 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
3987 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3988 const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
3989 WS_HEAP *heap, void *ret, ULONG size )
3991 ULONG i;
3992 HRESULT hr;
3993 char *buf;
3995 if (!desc) return E_INVALIDARG;
3996 if (desc->structOptions) FIXME( "struct options %08x not supported\n", desc->structOptions );
3998 switch (option)
4000 case WS_READ_REQUIRED_POINTER:
4001 case WS_READ_OPTIONAL_POINTER:
4002 case WS_READ_NILLABLE_POINTER:
4003 if (size != sizeof(void *)) return E_INVALIDARG;
4004 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
4005 break;
4007 case WS_READ_REQUIRED_VALUE:
4008 case WS_READ_NILLABLE_VALUE:
4009 if (size != desc->size) return E_INVALIDARG;
4010 buf = ret;
4011 break;
4013 default:
4014 FIXME( "unhandled read option %u\n", option );
4015 return E_NOTIMPL;
4018 for (i = 0; i < desc->fieldCount; i++)
4020 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
4021 break;
4024 switch (option)
4026 case WS_READ_REQUIRED_POINTER:
4027 if (hr != S_OK)
4029 ws_free( heap, buf );
4030 return hr;
4032 *(char **)ret = buf;
4033 return S_OK;
4035 case WS_READ_OPTIONAL_POINTER:
4036 case WS_READ_NILLABLE_POINTER:
4037 if (is_nil_value( buf, desc->size ))
4039 ws_free( heap, buf );
4040 buf = NULL;
4042 *(char **)ret = buf;
4043 return S_OK;
4045 case WS_READ_REQUIRED_VALUE:
4046 case WS_READ_NILLABLE_VALUE:
4047 return hr;
4049 default:
4050 ERR( "unhandled read option %u\n", option );
4051 return E_NOTIMPL;
4055 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
4056 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4057 const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
4058 void *value, ULONG size )
4060 HRESULT hr;
4062 switch (mapping)
4064 case WS_ELEMENT_TYPE_MAPPING:
4065 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
4066 if ((hr = read_type_next_element_node( reader, localname, ns )) != S_OK) return hr;
4067 break;
4069 case WS_ANY_ELEMENT_TYPE_MAPPING:
4070 case WS_ATTRIBUTE_TYPE_MAPPING:
4071 break;
4073 default:
4074 FIXME( "unhandled mapping %u\n", mapping );
4075 return E_NOTIMPL;
4078 switch (type)
4080 case WS_BOOL_TYPE:
4081 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4082 return hr;
4083 break;
4085 case WS_INT8_TYPE:
4086 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4087 return hr;
4088 break;
4090 case WS_INT16_TYPE:
4091 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4092 return hr;
4093 break;
4095 case WS_INT32_TYPE:
4096 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4097 return hr;
4098 break;
4100 case WS_INT64_TYPE:
4101 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4102 return hr;
4103 break;
4105 case WS_UINT8_TYPE:
4106 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4107 return hr;
4108 break;
4110 case WS_UINT16_TYPE:
4111 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4112 return hr;
4113 break;
4115 case WS_UINT32_TYPE:
4116 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4117 return hr;
4118 break;
4120 case WS_UINT64_TYPE:
4121 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4122 return hr;
4123 break;
4125 case WS_DOUBLE_TYPE:
4126 if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4127 return hr;
4128 break;
4130 case WS_DATETIME_TYPE:
4131 if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4132 return hr;
4133 break;
4135 case WS_GUID_TYPE:
4136 if ((hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4137 return hr;
4138 break;
4140 case WS_WSZ_TYPE:
4141 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4142 return hr;
4143 break;
4145 case WS_BYTES_TYPE:
4146 if ((hr = read_type_bytes( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4147 return hr;
4148 break;
4150 case WS_STRUCT_TYPE:
4151 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4152 return hr;
4153 break;
4155 case WS_ENUM_TYPE:
4156 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
4157 return hr;
4158 break;
4160 default:
4161 FIXME( "type %u not supported\n", type );
4162 return E_NOTIMPL;
4165 switch (mapping)
4167 case WS_ELEMENT_TYPE_MAPPING:
4168 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
4169 return read_type_next_node( reader );
4171 case WS_ATTRIBUTE_TYPE_MAPPING:
4172 default:
4173 return S_OK;
4177 /**************************************************************************
4178 * WsReadType [webservices.@]
4180 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
4181 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
4182 ULONG size, WS_ERROR *error )
4184 struct reader *reader = (struct reader *)handle;
4185 HRESULT hr;
4187 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
4188 size, error );
4189 if (error) FIXME( "ignoring error parameter\n" );
4191 if (!reader || !value) return E_INVALIDARG;
4193 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
4194 return hr;
4196 switch (mapping)
4198 case WS_ELEMENT_TYPE_MAPPING:
4199 if ((hr = read_node( reader )) != S_OK) return hr;
4200 break;
4202 default:
4203 break;
4206 if (!read_end_of_data( reader )) return WS_E_INVALID_FORMAT;
4207 return S_OK;
4210 /**************************************************************************
4211 * WsReadElement [webservices.@]
4213 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
4214 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
4215 WS_ERROR *error )
4217 struct reader *reader = (struct reader *)handle;
4219 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
4220 if (error) FIXME( "ignoring error parameter\n" );
4222 if (!reader || !desc || !value) return E_INVALIDARG;
4224 return read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
4225 desc->elementNs, desc->typeDescription, option, heap, value, size );
4228 /**************************************************************************
4229 * WsReadValue [webservices.@]
4231 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
4232 WS_ERROR *error )
4234 struct reader *reader = (struct reader *)handle;
4235 WS_TYPE type = map_value_type( value_type );
4237 TRACE( "%p %u %p %u %p\n", handle, type, value, size, error );
4238 if (error) FIXME( "ignoring error parameter\n" );
4240 if (!reader || !value || type == ~0u) return E_INVALIDARG;
4242 return read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
4243 NULL, value, size );
4246 /**************************************************************************
4247 * WsSetErrorProperty [webservices.@]
4249 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
4250 ULONG size )
4252 struct error *error = (struct error *)handle;
4254 TRACE( "%p %u %p %u\n", handle, id, value, size );
4256 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
4257 return prop_set( error->prop, error->prop_count, id, value, size );
4260 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
4262 static const char bom[] = {0xef,0xbb,0xbf};
4263 const unsigned char *p = data;
4265 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
4266 (size > 2 && !(*offset = 0));
4269 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
4271 static const char bom[] = {0xff,0xfe};
4272 const unsigned char *p = data;
4274 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
4275 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
4278 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
4280 WS_CHARSET ret = 0;
4282 /* FIXME: parse xml declaration */
4284 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
4285 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
4286 else
4288 FIXME( "charset not recognized\n" );
4289 return 0;
4292 TRACE( "detected charset %u\n", ret );
4293 return ret;
4296 static void set_input_buffer( struct reader *reader, struct xmlbuf *buf, const unsigned char *data, ULONG size )
4298 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
4299 reader->input_buf = buf;
4300 reader->input_data = data;
4301 reader->input_size = size;
4303 reader->read_size = reader->input_size;
4304 reader->read_pos = 0;
4305 reader->read_bufptr = reader->input_data;
4308 /**************************************************************************
4309 * WsSetInput [webservices.@]
4311 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
4312 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
4313 ULONG count, WS_ERROR *error )
4315 struct reader *reader = (struct reader *)handle;
4316 struct node *node;
4317 HRESULT hr;
4318 ULONG i, offset = 0;
4320 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
4321 if (error) FIXME( "ignoring error parameter\n" );
4323 if (!reader) return E_INVALIDARG;
4325 for (i = 0; i < count; i++)
4327 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
4328 properties[i].valueSize );
4329 if (hr != S_OK) return hr;
4332 if ((hr = read_init_state( reader )) != S_OK) return hr;
4334 switch (encoding->encodingType)
4336 case WS_XML_READER_ENCODING_TYPE_TEXT:
4338 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
4339 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
4340 WS_CHARSET charset = text->charSet;
4342 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
4344 FIXME( "charset detection on input type %u not supported\n", input->inputType );
4345 return E_NOTIMPL;
4348 if (charset == WS_CHARSET_AUTO)
4349 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
4351 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
4352 &charset, sizeof(charset) );
4353 if (hr != S_OK) return hr;
4354 break;
4356 default:
4357 FIXME( "encoding type %u not supported\n", encoding->encodingType );
4358 return E_NOTIMPL;
4360 switch (input->inputType)
4362 case WS_XML_READER_INPUT_TYPE_BUFFER:
4364 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
4365 set_input_buffer( reader, NULL, (const unsigned char *)buf->encodedData + offset,
4366 buf->encodedDataSize - offset );
4367 break;
4369 default:
4370 FIXME( "input type %u not supported\n", input->inputType );
4371 return E_NOTIMPL;
4374 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
4375 read_insert_bof( reader, node );
4376 return S_OK;
4379 /**************************************************************************
4380 * WsSetInputToBuffer [webservices.@]
4382 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
4383 const WS_XML_READER_PROPERTY *properties, ULONG count,
4384 WS_ERROR *error )
4386 struct reader *reader = (struct reader *)handle;
4387 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
4388 WS_CHARSET charset;
4389 struct node *node;
4390 HRESULT hr;
4391 ULONG i, offset = 0;
4393 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
4394 if (error) FIXME( "ignoring error parameter\n" );
4396 if (!reader || !xmlbuf) return E_INVALIDARG;
4398 for (i = 0; i < count; i++)
4400 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
4401 properties[i].valueSize );
4402 if (hr != S_OK) return hr;
4405 if ((hr = read_init_state( reader )) != S_OK) return hr;
4407 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
4408 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
4409 &charset, sizeof(charset) );
4410 if (hr != S_OK) return hr;
4412 set_input_buffer( reader, xmlbuf, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
4413 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
4414 read_insert_bof( reader, node );
4415 return S_OK;
4418 /**************************************************************************
4419 * WsXmlStringEquals [webservices.@]
4421 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
4423 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
4424 if (error) FIXME( "ignoring error parameter\n" );
4426 if (!str1 || !str2) return E_INVALIDARG;
4428 if (str1->length != str2->length) return S_FALSE;
4429 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
4430 return S_FALSE;
4433 /**************************************************************************
4434 * WsGetReaderPosition [webservices.@]
4436 HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
4438 struct reader *reader = (struct reader *)handle;
4440 TRACE( "%p %p %p\n", handle, pos, error );
4441 if (error) FIXME( "ignoring error parameter\n" );
4443 if (!reader || !pos) return E_INVALIDARG;
4444 if (!reader->input_buf) return WS_E_INVALID_OPERATION;
4446 pos->buffer = (WS_XML_BUFFER *)reader->input_buf;
4447 pos->node = reader->current;
4448 return S_OK;
4451 /**************************************************************************
4452 * WsSetReaderPosition [webservices.@]
4454 HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
4456 struct reader *reader = (struct reader *)handle;
4458 TRACE( "%p %p %p\n", handle, pos, error );
4459 if (error) FIXME( "ignoring error parameter\n" );
4461 if (!reader || !pos || (struct xmlbuf *)pos->buffer != reader->input_buf) return E_INVALIDARG;
4462 if (!reader->input_buf) return WS_E_INVALID_OPERATION;
4464 reader->current = pos->node;
4465 return S_OK;