webservices: Add generic property handlers.
[wine.git] / dlls / webservices / reader.c
blob555ab71b648ae3c2194467afb3019a0283303250
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 static const struct prop_desc heap_props[] =
147 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_MAX_SIZE */
148 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_TRIM_SIZE */
149 { sizeof(SIZE_T), TRUE }, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
150 { sizeof(SIZE_T), TRUE } /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
153 struct heap
155 HANDLE handle;
156 ULONG prop_count;
157 struct prop prop[sizeof(heap_props)/sizeof(heap_props[0])];
160 void *ws_alloc( WS_HEAP *handle, SIZE_T size )
162 struct heap *heap = (struct heap *)handle;
163 return HeapAlloc( heap->handle, 0, size );
166 static void *ws_alloc_zero( WS_HEAP *handle, SIZE_T size )
168 struct heap *heap = (struct heap *)handle;
169 return HeapAlloc( heap->handle, HEAP_ZERO_MEMORY, size );
172 void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
174 struct heap *heap = (struct heap *)handle;
175 return HeapReAlloc( heap->handle, 0, ptr, size );
178 static void *ws_realloc_zero( WS_HEAP *handle, void *ptr, SIZE_T size )
180 struct heap *heap = (struct heap *)handle;
181 return HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, size );
184 void ws_free( WS_HEAP *handle, void *ptr )
186 struct heap *heap = (struct heap *)handle;
187 HeapFree( heap->handle, 0, ptr );
190 /**************************************************************************
191 * WsAlloc [webservices.@]
193 HRESULT WINAPI WsAlloc( WS_HEAP *handle, SIZE_T size, void **ptr, WS_ERROR *error )
195 void *mem;
197 TRACE( "%p %u %p %p\n", handle, (ULONG)size, ptr, error );
198 if (error) FIXME( "ignoring error parameter\n" );
200 if (!handle || !ptr) return E_INVALIDARG;
202 if (!(mem = ws_alloc( handle, size ))) return E_OUTOFMEMORY;
203 *ptr = mem;
204 return S_OK;
207 static struct heap *alloc_heap(void)
209 static const ULONG count = sizeof(heap_props)/sizeof(heap_props[0]);
210 struct heap *ret;
211 ULONG size = sizeof(*ret) + prop_size( heap_props, count );
213 if (!(ret = heap_alloc_zero( size ))) return NULL;
214 prop_init( heap_props, count, ret->prop, &ret[1] );
215 ret->prop_count = count;
216 return ret;
219 /**************************************************************************
220 * WsCreateHeap [webservices.@]
222 HRESULT WINAPI WsCreateHeap( SIZE_T max_size, SIZE_T trim_size, const WS_HEAP_PROPERTY *properties,
223 ULONG count, WS_HEAP **handle, WS_ERROR *error )
225 struct heap *heap;
227 TRACE( "%u %u %p %u %p %p\n", (ULONG)max_size, (ULONG)trim_size, properties, count, handle, error );
228 if (error) FIXME( "ignoring error parameter\n" );
230 if (!handle || count) return E_INVALIDARG;
231 if (!(heap = alloc_heap())) return E_OUTOFMEMORY;
233 prop_set( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_MAX_SIZE, &max_size, sizeof(max_size) );
234 prop_set( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_TRIM_SIZE, &trim_size, sizeof(trim_size) );
236 if (!(heap->handle = HeapCreate( 0, 0, max_size )))
238 heap_free( heap );
239 return E_OUTOFMEMORY;
242 *handle = (WS_HEAP *)heap;
243 return S_OK;
246 /**************************************************************************
247 * WsFreeHeap [webservices.@]
249 void WINAPI WsFreeHeap( WS_HEAP *handle )
251 struct heap *heap = (struct heap *)handle;
253 TRACE( "%p\n", handle );
255 if (!heap) return;
256 HeapDestroy( heap->handle );
257 heap_free( heap );
260 struct node *alloc_node( WS_XML_NODE_TYPE type )
262 struct node *ret;
264 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
265 ret->hdr.node.nodeType = type;
266 list_init( &ret->entry );
267 list_init( &ret->children );
268 return ret;
271 void free_attribute( WS_XML_ATTRIBUTE *attr )
273 if (!attr) return;
274 heap_free( attr->prefix );
275 heap_free( attr->localName );
276 heap_free( attr->ns );
277 heap_free( attr->value );
278 heap_free( attr );
281 void free_node( struct node *node )
283 if (!node) return;
284 switch (node_type( node ))
286 case WS_XML_NODE_TYPE_ELEMENT:
288 WS_XML_ELEMENT_NODE *elem = &node->hdr;
289 ULONG i;
291 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
292 heap_free( elem->attributes );
293 heap_free( elem->prefix );
294 heap_free( elem->localName );
295 heap_free( elem->ns );
296 break;
298 case WS_XML_NODE_TYPE_TEXT:
300 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
301 heap_free( text->text );
302 break;
304 case WS_XML_NODE_TYPE_COMMENT:
306 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
307 heap_free( comment->value.bytes );
308 break;
310 case WS_XML_NODE_TYPE_CDATA:
311 case WS_XML_NODE_TYPE_END_CDATA:
312 case WS_XML_NODE_TYPE_END_ELEMENT:
313 case WS_XML_NODE_TYPE_EOF:
314 case WS_XML_NODE_TYPE_BOF:
315 break;
317 default:
318 ERR( "unhandled type %u\n", node_type( node ) );
319 break;
321 heap_free( node );
324 void destroy_nodes( struct node *node )
326 struct list *ptr;
328 if (!node) return;
329 while ((ptr = list_head( &node->children )))
331 struct node *child = LIST_ENTRY( ptr, struct node, entry );
332 list_remove( &child->entry );
333 destroy_nodes( child );
335 free_node( node );
338 static const struct prop_desc reader_props[] =
340 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
341 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
342 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
343 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
344 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
345 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
346 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
347 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
348 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
349 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
350 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
351 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
352 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
353 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
354 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
357 enum reader_state
359 READER_STATE_INITIAL,
360 READER_STATE_BOF,
361 READER_STATE_STARTELEMENT,
362 READER_STATE_STARTATTRIBUTE,
363 READER_STATE_STARTCDATA,
364 READER_STATE_CDATA,
365 READER_STATE_TEXT,
366 READER_STATE_ENDELEMENT,
367 READER_STATE_ENDCDATA,
368 READER_STATE_COMMENT,
369 READER_STATE_EOF
372 struct prefix
374 WS_XML_STRING str;
375 WS_XML_STRING ns;
378 struct reader
380 ULONG read_size;
381 ULONG read_pos;
382 const unsigned char *read_bufptr;
383 enum reader_state state;
384 struct node *root;
385 struct node *current;
386 ULONG current_attr;
387 struct prefix *prefixes;
388 ULONG nb_prefixes;
389 ULONG nb_prefixes_allocated;
390 WS_XML_READER_INPUT_TYPE input_type;
391 const unsigned char *input_data;
392 ULONG input_size;
393 ULONG prop_count;
394 struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])];
397 static struct reader *alloc_reader(void)
399 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
400 struct reader *ret;
401 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
403 if (!(ret = heap_alloc_zero( size ))) return NULL;
404 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
406 heap_free( ret );
407 return NULL;
409 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
411 prop_init( reader_props, count, ret->prop, &ret[1] );
412 ret->prop_count = count;
413 return ret;
416 static void clear_prefixes( struct prefix *prefixes, ULONG count )
418 ULONG i;
419 for (i = 0; i < count; i++)
421 heap_free( prefixes[i].str.bytes );
422 prefixes[i].str.bytes = NULL;
423 prefixes[i].str.length = 0;
425 heap_free( prefixes[i].ns.bytes );
426 prefixes[i].ns.bytes = NULL;
427 prefixes[i].ns.length = 0;
431 static void free_reader( struct reader *reader )
433 if (!reader) return;
434 destroy_nodes( reader->root );
435 clear_prefixes( reader->prefixes, reader->nb_prefixes );
436 heap_free( reader->prefixes );
437 heap_free( reader );
440 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
442 if (str)
444 heap_free( prefix->str.bytes );
445 if (!(prefix->str.bytes = heap_alloc( str->length ))) return E_OUTOFMEMORY;
446 memcpy( prefix->str.bytes, str->bytes, str->length );
447 prefix->str.length = str->length;
450 heap_free( prefix->ns.bytes );
451 if (!(prefix->ns.bytes = heap_alloc( ns->length ))) return E_OUTOFMEMORY;
452 memcpy( prefix->ns.bytes, ns->bytes, ns->length );
453 prefix->ns.length = ns->length;
455 return S_OK;
458 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
460 ULONG i;
461 HRESULT hr;
463 for (i = 0; i < reader->nb_prefixes; i++)
465 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
466 return set_prefix( &reader->prefixes[i], NULL, ns );
468 if (i >= reader->nb_prefixes_allocated)
470 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
471 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
472 if (!tmp) return E_OUTOFMEMORY;
473 reader->prefixes = tmp;
474 reader->nb_prefixes_allocated *= 2;
477 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
478 reader->nb_prefixes++;
479 return S_OK;
482 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
484 ULONG i;
485 for (i = 0; i < reader->nb_prefixes; i++)
487 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
488 return &reader->prefixes[i].ns;
490 return NULL;
493 static void read_insert_eof( struct reader *reader, struct node *eof )
495 if (!reader->root) reader->root = eof;
496 else
498 eof->parent = reader->root;
499 list_add_tail( &reader->root->children, &eof->entry );
501 reader->current = eof;
504 static void read_insert_bof( struct reader *reader, struct node *bof )
506 reader->root->parent = bof;
507 list_add_tail( &bof->children, &reader->root->entry );
508 reader->current = reader->root = bof;
511 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
513 node->parent = parent;
514 if (node->parent == reader->root)
516 struct list *eof = list_tail( &reader->root->children );
517 list_add_before( eof, &node->entry );
519 else list_add_tail( &parent->children, &node->entry );
520 reader->current = node;
523 static HRESULT read_init_state( struct reader *reader )
525 struct node *node;
527 destroy_nodes( reader->root );
528 reader->root = NULL;
529 clear_prefixes( reader->prefixes, reader->nb_prefixes );
530 reader->nb_prefixes = 1;
531 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
532 read_insert_eof( reader, node );
533 reader->state = READER_STATE_INITIAL;
534 return S_OK;
537 /**************************************************************************
538 * WsCreateReader [webservices.@]
540 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
541 WS_XML_READER **handle, WS_ERROR *error )
543 struct reader *reader;
544 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
545 WS_CHARSET charset = WS_CHARSET_UTF8;
546 BOOL read_decl = TRUE;
547 HRESULT hr;
549 TRACE( "%p %u %p %p\n", properties, count, handle, error );
550 if (error) FIXME( "ignoring error parameter\n" );
552 if (!handle) return E_INVALIDARG;
553 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
555 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
556 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
557 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
558 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
559 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
561 for (i = 0; i < count; i++)
563 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
564 properties[i].valueSize );
565 if (hr != S_OK)
567 free_reader( reader );
568 return hr;
572 if ((hr = read_init_state( reader )) != S_OK)
574 free_reader( reader );
575 return hr;
578 *handle = (WS_XML_READER *)reader;
579 return S_OK;
582 /**************************************************************************
583 * WsFreeReader [webservices.@]
585 void WINAPI WsFreeReader( WS_XML_READER *handle )
587 struct reader *reader = (struct reader *)handle;
589 TRACE( "%p\n", handle );
590 free_reader( reader );
593 /**************************************************************************
594 * WsFillReader [webservices.@]
596 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
597 WS_ERROR *error )
599 struct reader *reader = (struct reader *)handle;
601 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
602 if (error) FIXME( "ignoring error parameter\n" );
604 if (!reader) return E_INVALIDARG;
606 /* FIXME: add support for stream input */
607 reader->read_size = min( min_size, reader->input_size );
608 reader->read_pos = 0;
610 return S_OK;
613 /**************************************************************************
614 * WsGetErrorProperty [webservices.@]
616 HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf,
617 ULONG size )
619 struct error *error = (struct error *)handle;
621 TRACE( "%p %u %p %u\n", handle, id, buf, size );
622 return prop_get( error->prop, error->prop_count, id, buf, size );
625 /**************************************************************************
626 * WsGetErrorString [webservices.@]
628 HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str )
630 FIXME( "%p %u %p: stub\n", handle, index, str );
631 return E_NOTIMPL;
634 /**************************************************************************
635 * WsGetHeapProperty [webservices.@]
637 HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
638 ULONG size, WS_ERROR *error )
640 struct heap *heap = (struct heap *)handle;
642 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
643 if (error) FIXME( "ignoring error parameter\n" );
645 return prop_get( heap->prop, heap->prop_count, id, buf, size );
648 /**************************************************************************
649 * WsGetNamespaceFromPrefix [webservices.@]
651 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
652 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
654 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
655 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
656 static const WS_XML_STRING empty_ns = {0, NULL};
657 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
658 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
659 struct reader *reader = (struct reader *)handle;
660 BOOL found = FALSE;
662 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
663 if (error) FIXME( "ignoring error parameter\n" );
665 if (!reader || !prefix || !ns) return E_INVALIDARG;
666 if (reader->state != READER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
668 if (!prefix->length)
670 *ns = &empty_ns;
671 found = TRUE;
673 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
675 *ns = &xml_ns;
676 found = TRUE;
678 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
680 *ns = &xmlns_ns;
681 found = TRUE;
683 else
685 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
686 ULONG i;
688 for (i = 0; i < elem->attributeCount; i++)
690 if (!elem->attributes[i]->isXmlNs) continue;
691 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
693 *ns = elem->attributes[i]->ns;
694 found = TRUE;
695 break;
700 if (!found)
702 if (required) return WS_E_INVALID_FORMAT;
703 *ns = NULL;
704 return S_FALSE;
706 return S_OK;
709 /**************************************************************************
710 * WsGetReaderNode [webservices.@]
712 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
713 WS_ERROR *error )
715 struct reader *reader = (struct reader *)handle;
717 TRACE( "%p %p %p\n", handle, node, error );
718 if (error) FIXME( "ignoring error parameter\n" );
720 if (!reader || !node) return E_INVALIDARG;
722 *node = &reader->current->hdr.node;
723 return S_OK;
726 /**************************************************************************
727 * WsGetReaderProperty [webservices.@]
729 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
730 void *buf, ULONG size, WS_ERROR *error )
732 struct reader *reader = (struct reader *)handle;
734 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
735 if (error) FIXME( "ignoring error parameter\n" );
737 if (!reader->input_type) return WS_E_INVALID_OPERATION;
739 if (id == WS_XML_READER_PROPERTY_CHARSET)
741 WS_CHARSET charset;
742 HRESULT hr;
744 if ((hr = prop_get( reader->prop, reader->prop_count, id, &charset, size )) != S_OK) return hr;
745 if (!charset) return WS_E_INVALID_FORMAT;
746 *(WS_CHARSET *)buf = charset;
747 return S_OK;
749 return prop_get( reader->prop, reader->prop_count, id, buf, size );
752 /**************************************************************************
753 * WsGetXmlAttribute [webservices.@]
755 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
756 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
758 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
759 return E_NOTIMPL;
762 WS_XML_STRING *alloc_xml_string( const unsigned char *data, ULONG len )
764 WS_XML_STRING *ret;
766 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
767 ret->length = len;
768 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
769 ret->dictionary = NULL;
770 ret->id = 0;
771 if (data) memcpy( ret->bytes, data, len );
772 return ret;
775 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *data, ULONG len )
777 WS_XML_UTF8_TEXT *ret;
779 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
780 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
781 ret->value.length = len;
782 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
783 ret->value.dictionary = NULL;
784 ret->value.id = 0;
785 if (data) memcpy( ret->value.bytes, data, len );
786 return ret;
789 static inline BOOL read_end_of_data( struct reader *reader )
791 return reader->read_pos >= reader->read_size;
794 static inline const unsigned char *read_current_ptr( struct reader *reader )
796 return &reader->read_bufptr[reader->read_pos];
799 /* UTF-8 support based on libs/wine/utf8.c */
801 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
802 static const char utf8_length[128] =
804 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
805 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
806 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
807 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
808 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
809 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
810 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
811 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
814 /* first byte mask depending on UTF-8 sequence length */
815 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
817 /* minimum Unicode value depending on UTF-8 sequence length */
818 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
820 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
822 unsigned int len, res;
823 unsigned char ch = reader->read_bufptr[reader->read_pos];
824 const unsigned char *end;
826 if (reader->read_pos >= reader->read_size) return 0;
828 if (ch < 0x80)
830 *skip = 1;
831 return ch;
833 len = utf8_length[ch - 0x80];
834 if (reader->read_pos + len >= reader->read_size) return 0;
835 end = reader->read_bufptr + reader->read_pos + len;
836 res = ch & utf8_mask[len];
838 switch (len)
840 case 3:
841 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
842 res = (res << 6) | ch;
843 case 2:
844 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
845 res = (res << 6) | ch;
846 case 1:
847 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
848 res = (res << 6) | ch;
849 if (res < utf8_minval[len]) break;
850 *skip = len + 1;
851 return res;
854 return 0;
857 static inline void read_skip( struct reader *reader, unsigned int count )
859 if (reader->read_pos + count > reader->read_size) return;
860 reader->read_pos += count;
863 static inline void read_rewind( struct reader *reader, unsigned int count )
865 reader->read_pos -= count;
868 static inline BOOL read_isnamechar( unsigned int ch )
870 /* FIXME: incomplete */
871 return (ch >= 'A' && ch <= 'Z') ||
872 (ch >= 'a' && ch <= 'z') ||
873 (ch >= '0' && ch <= '9') ||
874 ch == '_' || ch == '-' || ch == '.' || ch == ':';
877 static inline BOOL read_isspace( unsigned int ch )
879 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
882 static inline void read_skip_whitespace( struct reader *reader )
884 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
885 reader->read_pos++;
888 static inline int read_cmp( struct reader *reader, const char *str, int len )
890 const unsigned char *ptr = read_current_ptr( reader );
892 if (len < 0) len = strlen( str );
893 if (reader->read_pos + len > reader->read_size) return -1;
894 while (len--)
896 if (*str != *ptr) return *ptr - *str;
897 str++; ptr++;
899 return 0;
902 static HRESULT read_xmldecl( struct reader *reader )
904 if (!reader->read_size) return WS_E_INVALID_FORMAT;
906 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
908 reader->state = READER_STATE_BOF;
909 return S_OK;
911 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
912 read_skip( reader, 6 );
914 /* FIXME: parse attributes */
915 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
916 reader->read_pos++;
918 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
919 read_skip( reader, 2 );
921 reader->state = READER_STATE_BOF;
922 return S_OK;
925 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
927 if (elem->attributeCount)
929 WS_XML_ATTRIBUTE **tmp;
930 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
931 return E_OUTOFMEMORY;
932 elem->attributes = tmp;
934 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
935 elem->attributes[elem->attributeCount++] = attr;
936 return S_OK;
939 static HRESULT parse_name( const unsigned char *str, unsigned int len,
940 WS_XML_STRING **prefix, WS_XML_STRING **localname )
942 const unsigned char *name_ptr = str, *prefix_ptr = NULL;
943 unsigned int i, name_len = len, prefix_len = 0;
945 for (i = 0; i < len; i++)
947 if (str[i] == ':')
949 prefix_ptr = str;
950 prefix_len = i;
951 name_ptr = &str[i + 1];
952 name_len -= i + 1;
953 break;
956 if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
957 if (!(*localname = alloc_xml_string( name_ptr, name_len )))
959 heap_free( *prefix );
960 return E_OUTOFMEMORY;
962 return S_OK;
965 static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
967 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
968 WS_XML_ATTRIBUTE *attr;
969 WS_XML_UTF8_TEXT *text;
970 unsigned int len = 0, ch, skip, quote;
971 const unsigned char *start;
972 WS_XML_STRING *prefix, *localname;
973 HRESULT hr = WS_E_INVALID_FORMAT;
975 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
977 start = read_current_ptr( reader );
978 for (;;)
980 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
981 if (!read_isnamechar( ch )) break;
982 read_skip( reader, skip );
983 len += skip;
985 if (!len) goto error;
987 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) goto error;
988 hr = E_OUTOFMEMORY;
989 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
991 heap_free( prefix );
992 attr->isXmlNs = 1;
993 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
995 heap_free( localname );
996 goto error;
998 attr->localName = localname;
1000 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1002 attr->isXmlNs = 1;
1003 attr->prefix = prefix;
1004 attr->localName = localname;
1006 else
1008 attr->prefix = prefix;
1009 attr->localName = localname;
1012 hr = WS_E_INVALID_FORMAT;
1013 read_skip_whitespace( reader );
1014 if (read_cmp( reader, "=", 1 )) goto error;
1015 read_skip( reader, 1 );
1017 read_skip_whitespace( reader );
1018 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) goto error;
1019 quote = read_utf8_char( reader, &skip );
1020 read_skip( reader, 1 );
1022 len = 0;
1023 start = read_current_ptr( reader );
1024 for (;;)
1026 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1027 if (ch == quote) break;
1028 read_skip( reader, skip );
1029 len += skip;
1031 read_skip( reader, 1 );
1033 hr = E_OUTOFMEMORY;
1034 if (attr->isXmlNs)
1036 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1037 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1038 if (!(text = alloc_utf8_text( NULL, 0 ))) goto error;
1040 else if (!(text = alloc_utf8_text( start, len ))) goto error;
1042 attr->value = &text->text;
1043 attr->singleQuote = (quote == '\'');
1045 *ret = attr;
1046 return S_OK;
1048 error:
1049 free_attribute( attr );
1050 return hr;
1053 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
1055 ULONG i;
1056 if (len1 != len2) return 1;
1057 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
1058 return 0;
1061 static struct node *read_find_parent( struct reader *reader, const WS_XML_STRING *prefix,
1062 const WS_XML_STRING *localname )
1064 struct node *parent;
1065 const WS_XML_STRING *str;
1067 for (parent = reader->current; parent; parent = parent->parent)
1069 if (node_type( parent ) == WS_XML_NODE_TYPE_BOF)
1071 if (!localname) return parent;
1072 return NULL;
1074 else if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
1076 if (!localname) return parent;
1078 str = parent->hdr.prefix;
1079 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
1080 str = parent->hdr.localName;
1081 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
1082 return parent;
1086 return NULL;
1089 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1091 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1092 const WS_XML_STRING *ns;
1093 ULONG i;
1095 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1096 if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1097 if (!elem->ns->length) elem->ns->bytes = (BYTE *)(elem->ns + 1); /* quirk */
1099 for (i = 0; i < elem->attributeCount; i++)
1101 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1102 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1103 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1104 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1106 return S_OK;
1109 static HRESULT read_element( struct reader *reader )
1111 unsigned int len = 0, ch, skip;
1112 const unsigned char *start;
1113 struct node *node = NULL, *parent;
1114 WS_XML_ELEMENT_NODE *elem;
1115 WS_XML_ATTRIBUTE *attr = NULL;
1116 HRESULT hr = WS_E_INVALID_FORMAT;
1118 if (read_end_of_data( reader ))
1120 struct list *eof = list_tail( &reader->root->children );
1121 reader->current = LIST_ENTRY( eof, struct node, entry );
1122 reader->state = READER_STATE_EOF;
1123 return S_OK;
1126 if (read_cmp( reader, "<", 1 )) goto error;
1127 read_skip( reader, 1 );
1128 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1130 read_rewind( reader, 1 );
1131 goto error;
1134 start = read_current_ptr( reader );
1135 for (;;)
1137 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1138 if (!read_isnamechar( ch )) break;
1139 read_skip( reader, skip );
1140 len += skip;
1142 if (!len) goto error;
1144 if (!(parent = read_find_parent( reader, NULL, NULL ))) goto error;
1146 hr = E_OUTOFMEMORY;
1147 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error;
1148 elem = (WS_XML_ELEMENT_NODE *)node;
1149 if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1151 reader->current_attr = 0;
1152 for (;;)
1154 read_skip_whitespace( reader );
1155 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1156 if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
1157 if ((hr = append_attribute( elem, attr )) != S_OK)
1159 free_attribute( attr );
1160 goto error;
1162 reader->current_attr++;
1164 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1166 read_insert_node( reader, parent, node );
1167 reader->state = READER_STATE_STARTELEMENT;
1168 return S_OK;
1170 error:
1171 free_node( node );
1172 return hr;
1175 static HRESULT read_text( struct reader *reader )
1177 unsigned int len = 0, ch, skip;
1178 const unsigned char *start;
1179 struct node *node;
1180 WS_XML_TEXT_NODE *text;
1181 WS_XML_UTF8_TEXT *utf8;
1183 start = read_current_ptr( reader );
1184 for (;;)
1186 if (read_end_of_data( reader )) break;
1187 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1188 if (ch == '<') break;
1189 read_skip( reader, skip );
1190 len += skip;
1193 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1194 text = (WS_XML_TEXT_NODE *)node;
1195 if (!(utf8 = alloc_utf8_text( start, len )))
1197 heap_free( node );
1198 return E_OUTOFMEMORY;
1200 text->text = &utf8->text;
1202 read_insert_node( reader, reader->current, node );
1203 reader->state = READER_STATE_TEXT;
1204 return S_OK;
1207 static HRESULT read_node( struct reader * );
1209 static HRESULT read_startelement( struct reader *reader )
1211 struct node *node;
1213 read_skip_whitespace( reader );
1214 if (!read_cmp( reader, "/>", 2 ))
1216 read_skip( reader, 2 );
1217 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1218 read_insert_node( reader, reader->current, node );
1219 reader->state = READER_STATE_ENDELEMENT;
1220 return S_OK;
1222 else if (!read_cmp( reader, ">", 1 ))
1224 read_skip( reader, 1 );
1225 return read_node( reader );
1227 return WS_E_INVALID_FORMAT;
1230 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
1232 HRESULT hr;
1234 switch (reader->state)
1236 case READER_STATE_INITIAL:
1237 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
1238 break;
1240 case READER_STATE_STARTELEMENT:
1241 if (found) *found = TRUE;
1242 return S_OK;
1244 default:
1245 break;
1248 read_skip_whitespace( reader );
1249 if ((hr = read_element( reader )) == S_OK && found)
1251 if (reader->state == READER_STATE_STARTELEMENT)
1252 *found = TRUE;
1253 else
1254 *found = FALSE;
1257 return hr;
1260 static HRESULT read_endelement( struct reader *reader )
1262 struct node *node, *parent;
1263 unsigned int len = 0, ch, skip;
1264 const unsigned char *start;
1265 WS_XML_STRING *prefix, *localname;
1266 HRESULT hr;
1268 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
1270 if (read_end_of_data( reader ))
1272 struct list *eof = list_tail( &reader->root->children );
1273 reader->current = LIST_ENTRY( eof, struct node, entry );
1274 reader->state = READER_STATE_EOF;
1275 return S_OK;
1278 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
1279 read_skip( reader, 2 );
1281 start = read_current_ptr( reader );
1282 for (;;)
1284 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1285 if (ch == '>')
1287 read_skip( reader, 1 );
1288 break;
1290 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
1291 read_skip( reader, skip );
1292 len += skip;
1295 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
1296 parent = read_find_parent( reader, prefix, localname );
1297 heap_free( prefix );
1298 heap_free( localname );
1299 if (!parent) return WS_E_INVALID_FORMAT;
1301 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1302 read_insert_node( reader, parent, node );
1303 reader->state = READER_STATE_ENDELEMENT;
1304 return S_OK;
1307 static HRESULT read_comment( struct reader *reader )
1309 unsigned int len = 0, ch, skip;
1310 const unsigned char *start;
1311 struct node *node;
1312 WS_XML_COMMENT_NODE *comment;
1314 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
1315 read_skip( reader, 4 );
1317 start = read_current_ptr( reader );
1318 for (;;)
1320 if (!read_cmp( reader, "-->", 3 ))
1322 read_skip( reader, 3 );
1323 break;
1325 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1326 read_skip( reader, skip );
1327 len += skip;
1330 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
1331 comment = (WS_XML_COMMENT_NODE *)node;
1332 if (!(comment->value.bytes = heap_alloc( len )))
1334 heap_free( node );
1335 return E_OUTOFMEMORY;
1337 memcpy( comment->value.bytes, start, len );
1338 comment->value.length = len;
1340 read_insert_node( reader, reader->current, node );
1341 reader->state = READER_STATE_COMMENT;
1342 return S_OK;
1345 static HRESULT read_startcdata( struct reader *reader )
1347 struct node *node;
1349 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
1350 read_skip( reader, 9 );
1352 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
1353 read_insert_node( reader, reader->current, node );
1354 reader->state = READER_STATE_STARTCDATA;
1355 return S_OK;
1358 static HRESULT read_cdata( struct reader *reader )
1360 unsigned int len = 0, ch, skip;
1361 const unsigned char *start;
1362 struct node *node;
1363 WS_XML_TEXT_NODE *text;
1364 WS_XML_UTF8_TEXT *utf8;
1366 start = read_current_ptr( reader );
1367 for (;;)
1369 if (!read_cmp( reader, "]]>", 3 )) break;
1370 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1371 read_skip( reader, skip );
1372 len += skip;
1375 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1376 text = (WS_XML_TEXT_NODE *)node;
1377 if (!(utf8 = alloc_utf8_text( start, len )))
1379 heap_free( node );
1380 return E_OUTOFMEMORY;
1382 text->text = &utf8->text;
1384 read_insert_node( reader, reader->current, node );
1385 reader->state = READER_STATE_CDATA;
1386 return S_OK;
1389 static HRESULT read_endcdata( struct reader *reader )
1391 struct node *node;
1393 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
1394 read_skip( reader, 3 );
1396 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_CDATA ))) return E_OUTOFMEMORY;
1397 read_insert_node( reader, reader->current->parent, node );
1398 reader->state = READER_STATE_ENDCDATA;
1399 return S_OK;
1402 static HRESULT read_node( struct reader *reader )
1404 HRESULT hr;
1406 for (;;)
1408 if (read_end_of_data( reader ))
1410 struct list *eof = list_tail( &reader->root->children );
1411 reader->current = LIST_ENTRY( eof, struct node, entry );
1412 reader->state = READER_STATE_EOF;
1413 return S_OK;
1415 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
1416 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
1417 else if (!read_cmp( reader, "<?", 2 ))
1419 hr = read_xmldecl( reader );
1420 if (FAILED( hr )) return hr;
1422 else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
1423 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
1424 else if (!read_cmp( reader, "<!--", 4 )) return read_comment( reader );
1425 else if (!read_cmp( reader, "<", 1 )) return read_element( reader );
1426 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement( reader );
1427 else return read_text( reader );
1431 /**************************************************************************
1432 * WsReadEndElement [webservices.@]
1434 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
1436 struct reader *reader = (struct reader *)handle;
1438 TRACE( "%p %p\n", handle, error );
1439 if (error) FIXME( "ignoring error parameter\n" );
1441 if (!reader) return E_INVALIDARG;
1442 return read_endelement( reader );
1445 /**************************************************************************
1446 * WsReadNode [webservices.@]
1448 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
1450 struct reader *reader = (struct reader *)handle;
1452 TRACE( "%p %p\n", handle, error );
1453 if (error) FIXME( "ignoring error parameter\n" );
1455 if (!reader) return E_INVALIDARG;
1456 return read_node( reader );
1459 /**************************************************************************
1460 * WsReadStartElement [webservices.@]
1462 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
1464 struct reader *reader = (struct reader *)handle;
1466 TRACE( "%p %p\n", handle, error );
1467 if (error) FIXME( "ignoring error parameter\n" );
1469 if (!reader) return E_INVALIDARG;
1470 return read_startelement( reader );
1473 /**************************************************************************
1474 * WsReadToStartElement [webservices.@]
1476 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
1477 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
1479 struct reader *reader = (struct reader *)handle;
1481 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
1482 if (error) FIXME( "ignoring error parameter\n" );
1484 if (!reader) return E_INVALIDARG;
1485 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
1487 return read_to_startelement( reader, found );
1490 static BOOL move_to_root_element( struct reader *reader )
1492 struct list *ptr;
1493 struct node *node;
1495 if (!(ptr = list_head( &reader->root->children ))) return FALSE;
1496 node = LIST_ENTRY( ptr, struct node, entry );
1497 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1499 reader->current = node;
1500 return TRUE;
1502 while ((ptr = list_next( &reader->root->children, &node->entry )))
1504 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1505 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1507 reader->current = next;
1508 return TRUE;
1510 node = next;
1512 return FALSE;
1515 static BOOL move_to_next_element( struct reader *reader )
1517 struct list *ptr;
1518 struct node *node = reader->current;
1520 while ((ptr = list_next( &node->parent->children, &node->entry )))
1522 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1523 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1525 reader->current = next;
1526 return TRUE;
1528 node = next;
1530 return FALSE;
1533 static BOOL move_to_prev_element( struct reader *reader )
1535 struct list *ptr;
1536 struct node *node = reader->current;
1538 while ((ptr = list_prev( &node->parent->children, &node->entry )))
1540 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
1541 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
1543 reader->current = prev;
1544 return TRUE;
1546 node = prev;
1548 return FALSE;
1551 static BOOL move_to_child_element( struct reader *reader )
1553 struct list *ptr;
1554 struct node *node;
1556 if (!(ptr = list_head( &reader->current->children ))) return FALSE;
1557 node = LIST_ENTRY( ptr, struct node, entry );
1558 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1560 reader->current = node;
1561 return TRUE;
1563 while ((ptr = list_next( &reader->current->children, &node->entry )))
1565 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1566 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1568 reader->current = next;
1569 return TRUE;
1571 node = next;
1573 return FALSE;
1576 static BOOL move_to_end_element( struct reader *reader )
1578 struct list *ptr;
1579 struct node *node = reader->current;
1581 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
1583 if ((ptr = list_tail( &node->children )))
1585 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
1586 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
1588 reader->current = tail;
1589 return TRUE;
1592 return FALSE;
1595 static BOOL move_to_parent_element( struct reader *reader )
1597 struct node *parent = reader->current->parent;
1599 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
1600 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
1602 reader->current = parent;
1603 return TRUE;
1605 return FALSE;
1608 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
1610 struct list *ptr;
1611 BOOL success = FALSE;
1612 HRESULT hr = S_OK;
1614 if (!read_end_of_data( reader ))
1616 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
1617 if (hr != S_OK) return hr;
1619 switch (move)
1621 case WS_MOVE_TO_ROOT_ELEMENT:
1622 success = move_to_root_element( reader );
1623 break;
1625 case WS_MOVE_TO_NEXT_ELEMENT:
1626 success = move_to_next_element( reader );
1627 break;
1629 case WS_MOVE_TO_PREVIOUS_ELEMENT:
1630 success = move_to_prev_element( reader );
1631 break;
1633 case WS_MOVE_TO_CHILD_ELEMENT:
1634 success = move_to_child_element( reader );
1635 break;
1637 case WS_MOVE_TO_END_ELEMENT:
1638 success = move_to_end_element( reader );
1639 break;
1641 case WS_MOVE_TO_PARENT_ELEMENT:
1642 success = move_to_parent_element( reader );
1643 break;
1645 case WS_MOVE_TO_FIRST_NODE:
1646 if ((ptr = list_head( &reader->current->parent->children )))
1648 reader->current = LIST_ENTRY( ptr, struct node, entry );
1649 success = TRUE;
1651 break;
1653 case WS_MOVE_TO_NEXT_NODE:
1654 if ((ptr = list_next( &reader->current->parent->children, &reader->current->entry )))
1656 reader->current = LIST_ENTRY( ptr, struct node, entry );
1657 success = TRUE;
1659 break;
1661 case WS_MOVE_TO_PREVIOUS_NODE:
1662 if ((ptr = list_prev( &reader->current->parent->children, &reader->current->entry )))
1664 reader->current = LIST_ENTRY( ptr, struct node, entry );
1665 success = TRUE;
1667 break;
1669 case WS_MOVE_TO_CHILD_NODE:
1670 if ((ptr = list_head( &reader->current->children )))
1672 reader->current = LIST_ENTRY( ptr, struct node, entry );
1673 success = TRUE;
1675 break;
1677 case WS_MOVE_TO_BOF:
1678 reader->current = reader->root;
1679 success = TRUE;
1680 break;
1682 case WS_MOVE_TO_EOF:
1683 if ((ptr = list_tail( &reader->root->children )))
1685 reader->current = LIST_ENTRY( ptr, struct node, entry );
1686 success = TRUE;
1688 break;
1690 default:
1691 FIXME( "unhandled move %u\n", move );
1692 return E_NOTIMPL;
1695 if (found)
1697 *found = success;
1698 return S_OK;
1700 return success ? S_OK : WS_E_INVALID_FORMAT;
1703 /**************************************************************************
1704 * WsMoveReader [webservices.@]
1706 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
1708 struct reader *reader = (struct reader *)handle;
1710 TRACE( "%p %u %p %p\n", handle, move, found, error );
1711 if (error) FIXME( "ignoring error parameter\n" );
1713 if (!reader) return E_INVALIDARG;
1714 if (!reader->input_type) return WS_E_INVALID_OPERATION;
1716 return read_move_to( reader, move, found );
1719 /**************************************************************************
1720 * WsReadStartAttribute [webservices.@]
1722 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
1724 struct reader *reader = (struct reader *)handle;
1725 WS_XML_ELEMENT_NODE *elem;
1727 TRACE( "%p %u %p\n", handle, index, error );
1728 if (error) FIXME( "ignoring error parameter\n" );
1730 if (!reader) return E_INVALIDARG;
1732 elem = &reader->current->hdr;
1733 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
1734 return WS_E_INVALID_FORMAT;
1736 reader->current_attr = index;
1737 reader->state = READER_STATE_STARTATTRIBUTE;
1738 return S_OK;
1741 /**************************************************************************
1742 * WsReadEndAttribute [webservices.@]
1744 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
1746 struct reader *reader = (struct reader *)handle;
1748 TRACE( "%p %p\n", handle, error );
1749 if (error) FIXME( "ignoring error parameter\n" );
1751 if (!reader) return E_INVALIDARG;
1753 if (reader->state != READER_STATE_STARTATTRIBUTE)
1754 return WS_E_INVALID_FORMAT;
1756 reader->state = READER_STATE_STARTELEMENT;
1757 return S_OK;
1760 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
1762 WCHAR *ret;
1764 switch (text->textType)
1766 case WS_XML_TEXT_TYPE_UTF8:
1768 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
1769 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
1770 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
1771 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
1772 ret[len] = 0;
1773 break;
1775 default:
1776 FIXME( "unhandled type %u\n", text->textType );
1777 return NULL;
1780 return ret;
1783 #define MAX_INT8 0x7f
1784 #define MIN_INT8 (-MAX_INT8 - 1)
1785 #define MAX_INT16 0x7fff
1786 #define MIN_INT16 (-MAX_INT16 - 1)
1787 #define MAX_INT32 0x7fffffff
1788 #define MIN_INT32 (-MAX_INT32 - 1)
1789 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1790 #define MIN_INT64 (-MAX_INT64 - 1)
1791 #define MAX_UINT8 0xff
1792 #define MAX_UINT16 0xffff
1793 #define MAX_UINT32 0xffffffff
1794 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1796 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
1798 BOOL negative = FALSE;
1799 const unsigned char *ptr = str;
1801 *ret = 0;
1802 while (len && read_isspace( *ptr )) { ptr++; len--; }
1803 while (len && read_isspace( ptr[len - 1] )) { len--; }
1804 if (!len) return WS_E_INVALID_FORMAT;
1806 if (*ptr == '-')
1808 negative = TRUE;
1809 ptr++;
1810 len--;
1812 if (!len) return WS_E_INVALID_FORMAT;
1814 while (len--)
1816 int val;
1818 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1819 val = *ptr - '0';
1820 if (negative) val = -val;
1822 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
1823 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
1825 return WS_E_NUMERIC_OVERFLOW;
1827 *ret = *ret * 10 + val;
1828 ptr++;
1831 return S_OK;
1834 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
1836 const unsigned char *ptr = str;
1838 *ret = 0;
1839 while (len && read_isspace( *ptr )) { ptr++; len--; }
1840 while (len && read_isspace( ptr[len - 1] )) { len--; }
1841 if (!len) return WS_E_INVALID_FORMAT;
1843 while (len--)
1845 unsigned int val;
1847 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1848 val = *ptr - '0';
1850 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
1851 *ret = *ret * 10 + val;
1852 ptr++;
1855 return S_OK;
1858 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
1860 WS_XML_TEXT_NODE *text;
1862 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
1863 return WS_E_INVALID_FORMAT;
1865 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
1866 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
1868 FIXME( "text type %u not supported\n", text->text->textType );
1869 return E_NOTIMPL;
1871 *ret = (WS_XML_UTF8_TEXT *)text->text;
1872 return S_OK;
1875 static HRESULT read_get_attribute_text( struct reader *reader, ULONG index, WS_XML_UTF8_TEXT **ret )
1877 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1878 WS_XML_ATTRIBUTE *attr;
1880 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
1881 return WS_E_INVALID_FORMAT;
1883 attr = elem->attributes[index];
1884 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
1886 FIXME( "text type %u not supported\n", attr->value->textType );
1887 return E_NOTIMPL;
1889 *ret = (WS_XML_UTF8_TEXT *)attr->value;
1890 return S_OK;
1893 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
1894 const WS_XML_STRING *ns, ULONG *index )
1896 ULONG i;
1897 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1899 if (!localname)
1901 *index = reader->current_attr;
1902 return TRUE;
1904 for (i = 0; i < elem->attributeCount; i++)
1906 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
1907 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
1909 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
1910 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
1912 *index = i;
1913 return TRUE;
1916 return FALSE;
1919 /**************************************************************************
1920 * WsFindAttribute [webservices.@]
1922 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
1923 const WS_XML_STRING *ns, BOOL required, ULONG *index,
1924 WS_ERROR *error )
1926 struct reader *reader = (struct reader *)handle;
1928 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
1929 required, index, error );
1930 if (error) FIXME( "ignoring error parameter\n" );
1932 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
1934 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
1935 return WS_E_INVALID_OPERATION;
1937 if (!find_attribute( reader, localname, ns, index ))
1939 if (required) return WS_E_INVALID_FORMAT;
1940 *index = ~0u;
1941 return S_FALSE;
1943 return S_OK;
1946 static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
1947 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
1948 WS_XML_UTF8_TEXT **ret, BOOL *found )
1950 switch (mapping)
1952 case WS_ATTRIBUTE_TYPE_MAPPING:
1954 ULONG index;
1955 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
1956 return read_get_attribute_text( reader, index, ret );
1958 case WS_ELEMENT_TYPE_MAPPING:
1959 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1960 case WS_ANY_ELEMENT_TYPE_MAPPING:
1962 HRESULT hr;
1963 *found = TRUE;
1964 if (localname)
1966 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1968 if (WsXmlStringEquals( localname, elem->localName, NULL ) != S_OK ||
1969 WsXmlStringEquals( ns, elem->ns, NULL ) != S_OK)
1971 *found = FALSE;
1972 return S_OK;
1974 if ((hr = read_startelement( reader )) != S_OK) return hr;
1976 return read_get_node_text( reader, ret );
1978 default:
1979 FIXME( "mapping %u not supported\n", mapping );
1980 return E_NOTIMPL;
1984 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
1985 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
1986 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
1987 WS_HEAP *heap, void *ret, ULONG size )
1989 WS_XML_UTF8_TEXT *utf8;
1990 HRESULT hr;
1991 BOOL found, val = FALSE;
1993 if (desc)
1995 FIXME( "description not supported\n" );
1996 return E_NOTIMPL;
1998 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
1999 if (found)
2001 ULONG len = utf8->value.length;
2002 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
2003 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
2004 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
2005 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
2006 else return WS_E_INVALID_FORMAT;
2009 switch (option)
2011 case WS_READ_REQUIRED_VALUE:
2012 if (!found) return WS_E_INVALID_FORMAT;
2013 if (size != sizeof(BOOL)) return E_INVALIDARG;
2014 *(BOOL *)ret = val;
2015 break;
2017 case WS_READ_REQUIRED_POINTER:
2018 if (!found) return WS_E_INVALID_FORMAT;
2019 /* fall through */
2021 case WS_READ_OPTIONAL_POINTER:
2023 BOOL *heap_val = NULL;
2024 if (size != sizeof(heap_val)) return E_INVALIDARG;
2025 if (found)
2027 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2028 *heap_val = val;
2030 *(BOOL **)ret = heap_val;
2031 break;
2033 default:
2034 FIXME( "read option %u not supported\n", option );
2035 return E_NOTIMPL;
2038 return S_OK;
2041 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
2042 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2043 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
2044 WS_HEAP *heap, void *ret, ULONG size )
2046 WS_XML_UTF8_TEXT *utf8;
2047 HRESULT hr;
2048 INT64 val;
2049 BOOL found;
2051 if (desc)
2053 FIXME( "description not supported\n" );
2054 return E_NOTIMPL;
2056 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2057 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
2058 return hr;
2060 switch (option)
2062 case WS_READ_REQUIRED_VALUE:
2063 if (!found) return WS_E_INVALID_FORMAT;
2064 if (size != sizeof(INT8)) return E_INVALIDARG;
2065 *(INT8 *)ret = val;
2066 break;
2068 case WS_READ_REQUIRED_POINTER:
2069 if (!found) return WS_E_INVALID_FORMAT;
2070 /* fall through */
2072 case WS_READ_OPTIONAL_POINTER:
2074 INT8 *heap_val = NULL;
2075 if (size != sizeof(heap_val)) return E_INVALIDARG;
2076 if (found)
2078 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2079 *heap_val = val;
2081 *(INT8 **)ret = heap_val;
2082 break;
2084 default:
2085 FIXME( "read option %u not supported\n", option );
2086 return E_NOTIMPL;
2089 return S_OK;
2092 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
2093 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2094 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
2095 WS_HEAP *heap, void *ret, ULONG size )
2097 WS_XML_UTF8_TEXT *utf8;
2098 HRESULT hr;
2099 INT64 val;
2100 BOOL found;
2102 if (desc)
2104 FIXME( "description not supported\n" );
2105 return E_NOTIMPL;
2107 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2108 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
2109 return hr;
2111 switch (option)
2113 case WS_READ_REQUIRED_VALUE:
2114 if (!found) return WS_E_INVALID_FORMAT;
2115 if (size != sizeof(INT16)) return E_INVALIDARG;
2116 *(INT16 *)ret = val;
2117 break;
2119 case WS_READ_REQUIRED_POINTER:
2120 if (!found) return WS_E_INVALID_FORMAT;
2121 /* fall through */
2123 case WS_READ_OPTIONAL_POINTER:
2125 INT16 *heap_val = NULL;
2126 if (size != sizeof(heap_val)) return E_INVALIDARG;
2127 if (found)
2129 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2130 *heap_val = val;
2132 *(INT16 **)ret = heap_val;
2133 break;
2135 default:
2136 FIXME( "read option %u not supported\n", option );
2137 return E_NOTIMPL;
2140 return S_OK;
2143 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
2144 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2145 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
2146 WS_HEAP *heap, void *ret, ULONG size )
2148 WS_XML_UTF8_TEXT *utf8;
2149 HRESULT hr;
2150 INT64 val;
2151 BOOL found;
2153 if (desc)
2155 FIXME( "description not supported\n" );
2156 return E_NOTIMPL;
2158 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2159 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
2160 return hr;
2162 switch (option)
2164 case WS_READ_REQUIRED_VALUE:
2165 if (!found) return WS_E_INVALID_FORMAT;
2166 if (size != sizeof(INT32)) return E_INVALIDARG;
2167 *(INT32 *)ret = val;
2168 break;
2170 case WS_READ_REQUIRED_POINTER:
2171 if (!found) return WS_E_INVALID_FORMAT;
2172 /* fall through */
2174 case WS_READ_OPTIONAL_POINTER:
2176 INT32 *heap_val = NULL;
2177 if (size != sizeof(heap_val)) return E_INVALIDARG;
2178 if (found)
2180 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2181 *heap_val = val;
2183 *(INT32 **)ret = heap_val;
2184 break;
2186 default:
2187 FIXME( "read option %u not supported\n", option );
2188 return E_NOTIMPL;
2191 return S_OK;
2194 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
2195 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2196 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
2197 WS_HEAP *heap, void *ret, ULONG size )
2199 WS_XML_UTF8_TEXT *utf8;
2200 HRESULT hr;
2201 INT64 val;
2202 BOOL found;
2204 if (desc)
2206 FIXME( "description not supported\n" );
2207 return E_NOTIMPL;
2209 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2210 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
2211 return hr;
2213 switch (option)
2215 case WS_READ_REQUIRED_VALUE:
2216 if (!found) return WS_E_INVALID_FORMAT;
2217 if (size != sizeof(INT64)) return E_INVALIDARG;
2218 *(INT64 *)ret = val;
2219 break;
2221 case WS_READ_REQUIRED_POINTER:
2222 if (!found) return WS_E_INVALID_FORMAT;
2223 /* fall through */
2225 case WS_READ_OPTIONAL_POINTER:
2227 INT64 *heap_val = NULL;
2228 if (size != sizeof(heap_val)) return E_INVALIDARG;
2229 if (found)
2231 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2232 *heap_val = val;
2234 *(INT64 **)ret = heap_val;
2235 break;
2237 default:
2238 FIXME( "read option %u not supported\n", option );
2239 return E_NOTIMPL;
2242 return S_OK;
2245 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
2246 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2247 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
2248 WS_HEAP *heap, void *ret, ULONG size )
2250 WS_XML_UTF8_TEXT *utf8;
2251 HRESULT hr;
2252 UINT64 val;
2253 BOOL found;
2255 if (desc)
2257 FIXME( "description not supported\n" );
2258 return E_NOTIMPL;
2260 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2261 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
2262 return hr;
2264 switch (option)
2266 case WS_READ_REQUIRED_VALUE:
2267 if (!found) return WS_E_INVALID_FORMAT;
2268 if (size != sizeof(UINT8)) return E_INVALIDARG;
2269 *(UINT8 *)ret = val;
2270 break;
2272 case WS_READ_REQUIRED_POINTER:
2273 if (!found) return WS_E_INVALID_FORMAT;
2274 /* fall through */
2276 case WS_READ_OPTIONAL_POINTER:
2278 UINT8 *heap_val = NULL;
2279 if (size != sizeof(heap_val)) return E_INVALIDARG;
2280 if (found)
2282 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2283 *heap_val = val;
2285 *(UINT8 **)ret = heap_val;
2286 break;
2288 default:
2289 FIXME( "read option %u not supported\n", option );
2290 return E_NOTIMPL;
2293 return S_OK;
2296 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
2297 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2298 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
2299 WS_HEAP *heap, void *ret, ULONG size )
2301 WS_XML_UTF8_TEXT *utf8;
2302 HRESULT hr;
2303 UINT64 val;
2304 BOOL found;
2306 if (desc)
2308 FIXME( "description not supported\n" );
2309 return E_NOTIMPL;
2311 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2312 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
2313 return hr;
2315 switch (option)
2317 case WS_READ_REQUIRED_VALUE:
2318 if (!found) return WS_E_INVALID_FORMAT;
2319 if (size != sizeof(UINT16)) return E_INVALIDARG;
2320 *(UINT16 *)ret = val;
2321 break;
2323 case WS_READ_REQUIRED_POINTER:
2324 if (!found) return WS_E_INVALID_FORMAT;
2325 /* fall through */
2327 case WS_READ_OPTIONAL_POINTER:
2329 UINT16 *heap_val = NULL;
2330 if (size != sizeof(heap_val)) return E_INVALIDARG;
2331 if (found)
2333 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2334 *heap_val = val;
2336 *(UINT16 **)ret = heap_val;
2337 break;
2339 default:
2340 FIXME( "read option %u not supported\n", option );
2341 return E_NOTIMPL;
2344 return S_OK;
2347 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
2348 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2349 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
2350 WS_HEAP *heap, void *ret, ULONG size )
2352 WS_XML_UTF8_TEXT *utf8;
2353 HRESULT hr;
2354 UINT64 val;
2355 BOOL found;
2357 if (desc)
2359 FIXME( "description not supported\n" );
2360 return E_NOTIMPL;
2362 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2363 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
2364 return hr;
2366 switch (option)
2368 case WS_READ_REQUIRED_VALUE:
2369 if (!found) return WS_E_INVALID_FORMAT;
2370 if (size != sizeof(UINT32)) return E_INVALIDARG;
2371 *(UINT32 *)ret = val;
2372 break;
2374 case WS_READ_REQUIRED_POINTER:
2375 if (!found) return WS_E_INVALID_FORMAT;
2376 /* fall through */
2378 case WS_READ_OPTIONAL_POINTER:
2380 UINT32 *heap_val = NULL;
2381 if (size != sizeof(heap_val)) return E_INVALIDARG;
2382 if (found)
2384 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2385 *heap_val = val;
2387 *(UINT32 **)ret = heap_val;
2388 break;
2390 default:
2391 FIXME( "read option %u not supported\n", option );
2392 return E_NOTIMPL;
2395 return S_OK;
2398 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
2399 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2400 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
2401 WS_HEAP *heap, void *ret, ULONG size )
2403 WS_XML_UTF8_TEXT *utf8;
2404 HRESULT hr;
2405 UINT64 val;
2406 BOOL found;
2408 if (desc)
2410 FIXME( "description not supported\n" );
2411 return E_NOTIMPL;
2413 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2414 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
2415 return hr;
2417 switch (option)
2419 case WS_READ_REQUIRED_VALUE:
2420 if (!found) return WS_E_INVALID_FORMAT;
2421 if (size != sizeof(UINT64)) return E_INVALIDARG;
2422 *(UINT64 *)ret = val;
2423 break;
2425 case WS_READ_REQUIRED_POINTER:
2426 if (!found) return WS_E_INVALID_FORMAT;
2427 /* fall through */
2429 case WS_READ_OPTIONAL_POINTER:
2431 UINT64 *heap_val = NULL;
2432 if (size != sizeof(heap_val)) return E_INVALIDARG;
2433 if (found)
2435 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2436 *heap_val = val;
2438 *(UINT64 **)ret = heap_val;
2439 break;
2441 default:
2442 FIXME( "read option %u not supported\n", option );
2443 return E_NOTIMPL;
2446 return S_OK;
2449 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
2450 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2451 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
2452 WS_HEAP *heap, WCHAR **ret, ULONG size )
2454 WS_XML_UTF8_TEXT *utf8;
2455 HRESULT hr;
2456 WCHAR *str = NULL;
2457 BOOL found;
2459 if (desc)
2461 FIXME( "description not supported\n" );
2462 return E_NOTIMPL;
2464 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2465 if (found && !(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
2467 switch (option)
2469 case WS_READ_REQUIRED_POINTER:
2470 if (!found) return WS_E_INVALID_FORMAT;
2471 /* fall through */
2473 case WS_READ_OPTIONAL_POINTER:
2474 if (size != sizeof(str)) return E_INVALIDARG;
2475 *ret = str;
2476 break;
2478 default:
2479 FIXME( "read option %u not supported\n", option );
2480 return E_NOTIMPL;
2483 return S_OK;
2486 static HRESULT get_enum_value( const WS_XML_UTF8_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
2488 ULONG i;
2489 for (i = 0; i < desc->valueCount; i++)
2491 if (WsXmlStringEquals( &text->value, desc->values[i].name, NULL ) == S_OK)
2493 *ret = desc->values[i].value;
2494 return S_OK;
2497 return WS_E_INVALID_FORMAT;
2500 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
2501 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2502 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
2503 WS_HEAP *heap, void *ret, ULONG size )
2505 WS_XML_UTF8_TEXT *utf8;
2506 HRESULT hr;
2507 int val = 0;
2508 BOOL found;
2510 if (!desc) return E_INVALIDARG;
2512 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2513 if (found && (hr = get_enum_value( utf8, desc, &val )) != S_OK) return hr;
2515 switch (option)
2517 case WS_READ_REQUIRED_VALUE:
2518 if (!found) return WS_E_INVALID_FORMAT;
2519 if (size != sizeof(int)) return E_INVALIDARG;
2520 *(int *)ret = val;
2521 break;
2523 case WS_READ_REQUIRED_POINTER:
2524 if (!found) return WS_E_INVALID_FORMAT;
2525 /* fall through */
2527 case WS_READ_OPTIONAL_POINTER:
2529 int *heap_val = NULL;
2530 if (size != sizeof(heap_val)) return E_INVALIDARG;
2531 if (found)
2533 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2534 *heap_val = val;
2536 *(int **)ret = heap_val;
2537 break;
2539 default:
2540 FIXME( "read option %u not supported\n", option );
2541 return E_NOTIMPL;
2544 return S_OK;
2547 static BOOL is_empty_text_node( const struct node *node )
2549 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
2550 const WS_XML_UTF8_TEXT *utf8;
2551 ULONG i;
2553 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
2554 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
2556 ERR( "unhandled text type %u\n", text->text->textType );
2557 return FALSE;
2559 utf8 = (const WS_XML_UTF8_TEXT *)text->text;
2560 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
2561 return TRUE;
2564 /* skips comment and empty text nodes */
2565 static HRESULT read_type_next_node( struct reader *reader )
2567 for (;;)
2569 HRESULT hr;
2570 WS_XML_NODE_TYPE type;
2572 if ((hr = read_node( reader )) != S_OK) return hr;
2573 type = node_type( reader->current );
2574 if (type == WS_XML_NODE_TYPE_COMMENT ||
2575 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
2576 return S_OK;
2580 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
2581 const WS_XML_STRING *ns )
2583 const WS_XML_ELEMENT_NODE *elem;
2584 HRESULT hr;
2585 BOOL found;
2587 if (!localname) return S_OK; /* assume reader is already correctly positioned */
2588 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
2589 if (!found) return WS_E_INVALID_FORMAT;
2591 elem = &reader->current->hdr;
2592 if (WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
2593 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK) return S_OK;
2595 return read_type_next_node( reader );
2598 static ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
2600 switch (type)
2602 case WS_INT8_TYPE:
2603 case WS_UINT8_TYPE:
2604 return sizeof(INT8);
2606 case WS_INT16_TYPE:
2607 case WS_UINT16_TYPE:
2608 return sizeof(INT16);
2610 case WS_BOOL_TYPE:
2611 case WS_INT32_TYPE:
2612 case WS_UINT32_TYPE:
2613 case WS_ENUM_TYPE:
2614 return sizeof(INT32);
2616 case WS_INT64_TYPE:
2617 case WS_UINT64_TYPE:
2618 return sizeof(INT64);
2620 case WS_WSZ_TYPE:
2621 return sizeof(WCHAR *);
2623 case WS_STRUCT_TYPE:
2624 return desc->size;
2626 default:
2627 ERR( "unhandled type %u\n", type );
2628 return 0;
2632 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
2633 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
2634 void *, ULONG );
2636 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
2637 WS_READ_OPTION option, WS_HEAP *heap, void **ret,
2638 ULONG size, ULONG *count )
2640 HRESULT hr;
2641 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
2642 char *buf;
2644 if (size != sizeof(void *)) return E_INVALIDARG;
2646 /* wrapper element */
2647 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
2648 return hr;
2650 item_size = get_type_size( desc->type, desc->typeDescription );
2651 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
2652 for (;;)
2654 if (nb_items >= nb_allocated)
2656 if (!(buf = ws_realloc_zero( heap, buf, nb_allocated * 2 * item_size )))
2657 return WS_E_QUOTA_EXCEEDED;
2658 nb_allocated *= 2;
2660 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
2661 desc->typeDescription, WS_READ_REQUIRED_VALUE, heap, buf + offset, item_size );
2662 if (hr == WS_E_INVALID_FORMAT) break;
2663 if (hr != S_OK)
2665 ws_free( heap, buf );
2666 return hr;
2668 offset += item_size;
2669 nb_items++;
2672 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
2674 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
2676 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
2677 desc->itemRange->maxItemCount );
2678 ws_free( heap, buf );
2679 return WS_E_INVALID_FORMAT;
2682 *count = nb_items;
2683 *ret = buf;
2685 return S_OK;
2688 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
2689 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
2691 HRESULT hr;
2692 BOOL found;
2694 if ((hr = read_to_startelement( reader, &found )) != S_OK) return S_OK;
2695 if (!found) return WS_E_INVALID_FORMAT;
2696 if ((hr = read_node( reader )) != S_OK) return hr;
2697 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
2699 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
2700 desc->typeDescription, option, heap, ret, size );
2703 static WS_READ_OPTION map_field_options( WS_TYPE type, ULONG options )
2705 if (options & ~(WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
2707 FIXME( "options %08x not supported\n", options );
2708 return 0;
2711 switch (type)
2713 case WS_BOOL_TYPE:
2714 case WS_INT8_TYPE:
2715 case WS_INT16_TYPE:
2716 case WS_INT32_TYPE:
2717 case WS_INT64_TYPE:
2718 case WS_UINT8_TYPE:
2719 case WS_UINT16_TYPE:
2720 case WS_UINT32_TYPE:
2721 case WS_UINT64_TYPE:
2722 case WS_ENUM_TYPE:
2723 return WS_READ_REQUIRED_VALUE;
2725 case WS_WSZ_TYPE:
2726 case WS_STRUCT_TYPE:
2727 return WS_READ_REQUIRED_POINTER;
2729 default:
2730 FIXME( "unhandled type %u\n", type );
2731 return 0;
2735 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
2736 WS_HEAP *heap, char *buf )
2738 char *ptr;
2739 WS_READ_OPTION option;
2740 ULONG size;
2741 HRESULT hr;
2743 if (!desc || !(option = map_field_options( desc->type, desc->options ))) return E_INVALIDARG;
2745 if (option == WS_READ_REQUIRED_VALUE)
2746 size = get_type_size( desc->type, desc->typeDescription );
2747 else
2748 size = sizeof(void *);
2750 ptr = buf + desc->offset;
2751 switch (desc->mapping)
2753 case WS_ATTRIBUTE_FIELD_MAPPING:
2754 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
2755 desc->typeDescription, option, heap, ptr, size );
2756 break;
2758 case WS_ELEMENT_FIELD_MAPPING:
2759 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
2760 desc->typeDescription, option, heap, ptr, size );
2761 break;
2763 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
2765 ULONG count;
2766 hr = read_type_repeating_element( reader, desc, option, heap, (void **)ptr, size, &count );
2767 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
2768 break;
2770 case WS_TEXT_FIELD_MAPPING:
2771 hr = read_type_text( reader, desc, option, heap, ptr, size );
2772 break;
2774 default:
2775 FIXME( "unhandled field mapping %u\n", desc->mapping );
2776 return E_NOTIMPL;
2779 if (hr == WS_E_INVALID_FORMAT && desc->options & WS_FIELD_OPTIONAL)
2781 switch (option)
2783 case WS_READ_REQUIRED_VALUE:
2784 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
2785 else memset( ptr, 0, size );
2786 return S_OK;
2788 case WS_READ_REQUIRED_POINTER:
2789 *(void **)ptr = NULL;
2790 return S_OK;
2792 default:
2793 ERR( "unhandled option %u\n", option );
2794 return E_NOTIMPL;
2798 return hr;
2801 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
2802 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2803 const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
2804 WS_HEAP *heap, void *ret, ULONG size )
2806 ULONG i;
2807 HRESULT hr;
2808 char *buf;
2810 if (!desc) return E_INVALIDARG;
2812 if (desc->structOptions)
2814 FIXME( "struct options %08x not supported\n", desc->structOptions );
2815 return E_NOTIMPL;
2818 switch (option)
2820 case WS_READ_REQUIRED_POINTER:
2821 case WS_READ_OPTIONAL_POINTER:
2822 if (size != sizeof(void *)) return E_INVALIDARG;
2823 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
2824 break;
2826 case WS_READ_REQUIRED_VALUE:
2827 if (size != desc->size) return E_INVALIDARG;
2828 buf = ret;
2829 break;
2831 default:
2832 FIXME( "unhandled read option %u\n", option );
2833 return E_NOTIMPL;
2836 for (i = 0; i < desc->fieldCount; i++)
2838 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
2839 break;
2842 switch (option)
2844 case WS_READ_REQUIRED_POINTER:
2845 if (hr != S_OK)
2847 ws_free( heap, buf );
2848 return hr;
2850 *(char **)ret = buf;
2851 return S_OK;
2853 case WS_READ_OPTIONAL_POINTER:
2854 if (hr != S_OK)
2856 ws_free( heap, buf );
2857 buf = NULL;
2859 *(char **)ret = buf;
2860 return S_OK;
2862 case WS_READ_REQUIRED_VALUE:
2863 return hr;
2865 default:
2866 ERR( "unhandled read option %u\n", option );
2867 return E_NOTIMPL;
2871 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
2872 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2873 const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
2874 void *value, ULONG size )
2876 HRESULT hr;
2878 switch (mapping)
2880 case WS_ELEMENT_TYPE_MAPPING:
2881 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2882 if ((hr = read_type_next_element_node( reader, localname, ns )) != S_OK) return hr;
2883 break;
2885 case WS_ANY_ELEMENT_TYPE_MAPPING:
2886 case WS_ATTRIBUTE_TYPE_MAPPING:
2887 break;
2889 default:
2890 FIXME( "unhandled mapping %u\n", mapping );
2891 return E_NOTIMPL;
2894 switch (type)
2896 case WS_STRUCT_TYPE:
2897 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2898 return hr;
2899 break;
2901 case WS_BOOL_TYPE:
2902 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2903 return hr;
2904 break;
2906 case WS_INT8_TYPE:
2907 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2908 return hr;
2909 break;
2911 case WS_INT16_TYPE:
2912 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2913 return hr;
2914 break;
2916 case WS_INT32_TYPE:
2917 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2918 return hr;
2919 break;
2921 case WS_INT64_TYPE:
2922 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2923 return hr;
2924 break;
2926 case WS_UINT8_TYPE:
2927 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2928 return hr;
2929 break;
2931 case WS_UINT16_TYPE:
2932 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2933 return hr;
2934 break;
2936 case WS_UINT32_TYPE:
2937 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2938 return hr;
2939 break;
2941 case WS_UINT64_TYPE:
2942 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2943 return hr;
2944 break;
2946 case WS_WSZ_TYPE:
2947 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2948 return hr;
2949 break;
2951 case WS_ENUM_TYPE:
2952 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2953 return hr;
2954 break;
2956 default:
2957 FIXME( "type %u not supported\n", type );
2958 return E_NOTIMPL;
2961 switch (mapping)
2963 case WS_ELEMENT_TYPE_MAPPING:
2964 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2965 return read_type_next_node( reader );
2967 case WS_ATTRIBUTE_TYPE_MAPPING:
2968 default:
2969 return S_OK;
2973 /**************************************************************************
2974 * WsReadType [webservices.@]
2976 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
2977 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
2978 ULONG size, WS_ERROR *error )
2980 struct reader *reader = (struct reader *)handle;
2981 HRESULT hr;
2983 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
2984 size, error );
2985 if (error) FIXME( "ignoring error parameter\n" );
2987 if (!reader || !value) return E_INVALIDARG;
2989 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
2990 return hr;
2992 switch (mapping)
2994 case WS_ELEMENT_TYPE_MAPPING:
2995 if ((hr = read_node( reader )) != S_OK) return hr;
2996 break;
2998 default:
2999 break;
3002 if (!read_end_of_data( reader )) return WS_E_INVALID_FORMAT;
3003 return S_OK;
3006 /**************************************************************************
3007 * WsSetErrorProperty [webservices.@]
3009 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
3010 ULONG size )
3012 struct error *error = (struct error *)handle;
3014 TRACE( "%p %u %p %u\n", handle, id, value, size );
3016 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
3017 return prop_set( error->prop, error->prop_count, id, value, size );
3020 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
3022 static const char bom[] = {0xef,0xbb,0xbf};
3023 const unsigned char *p = data;
3025 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
3026 (size > 2 && !(*offset = 0));
3029 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
3031 static const char bom[] = {0xff,0xfe};
3032 const unsigned char *p = data;
3034 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
3035 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
3038 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
3040 WS_CHARSET ret = 0;
3042 /* FIXME: parse xml declaration */
3044 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
3045 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
3046 else
3048 FIXME( "charset not recognized\n" );
3049 return 0;
3052 TRACE( "detected charset %u\n", ret );
3053 return ret;
3056 static void set_input_buffer( struct reader *reader, const unsigned char *data, ULONG size )
3058 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
3059 reader->input_data = data;
3060 reader->input_size = size;
3062 reader->read_size = reader->input_size;
3063 reader->read_pos = 0;
3064 reader->read_bufptr = reader->input_data;
3067 /**************************************************************************
3068 * WsSetInput [webservices.@]
3070 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
3071 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
3072 ULONG count, WS_ERROR *error )
3074 struct reader *reader = (struct reader *)handle;
3075 struct node *node;
3076 HRESULT hr;
3077 ULONG i, offset = 0;
3079 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
3080 if (error) FIXME( "ignoring error parameter\n" );
3082 if (!reader) return E_INVALIDARG;
3084 for (i = 0; i < count; i++)
3086 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
3087 properties[i].valueSize );
3088 if (hr != S_OK) return hr;
3091 if ((hr = read_init_state( reader )) != S_OK) return hr;
3093 switch (encoding->encodingType)
3095 case WS_XML_READER_ENCODING_TYPE_TEXT:
3097 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
3098 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
3099 WS_CHARSET charset = text->charSet;
3101 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
3103 FIXME( "charset detection on input type %u not supported\n", input->inputType );
3104 return E_NOTIMPL;
3107 if (charset == WS_CHARSET_AUTO)
3108 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
3110 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
3111 &charset, sizeof(charset) );
3112 if (hr != S_OK) return hr;
3113 break;
3115 default:
3116 FIXME( "encoding type %u not supported\n", encoding->encodingType );
3117 return E_NOTIMPL;
3119 switch (input->inputType)
3121 case WS_XML_READER_INPUT_TYPE_BUFFER:
3123 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
3124 set_input_buffer( reader, (const unsigned char *)buf->encodedData + offset, buf->encodedDataSize - offset );
3125 break;
3127 default:
3128 FIXME( "input type %u not supported\n", input->inputType );
3129 return E_NOTIMPL;
3132 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
3133 read_insert_bof( reader, node );
3134 return S_OK;
3137 /**************************************************************************
3138 * WsSetInputToBuffer [webservices.@]
3140 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
3141 const WS_XML_READER_PROPERTY *properties, ULONG count,
3142 WS_ERROR *error )
3144 struct reader *reader = (struct reader *)handle;
3145 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
3146 WS_CHARSET charset;
3147 struct node *node;
3148 HRESULT hr;
3149 ULONG i, offset = 0;
3151 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
3152 if (error) FIXME( "ignoring error parameter\n" );
3154 if (!reader || !xmlbuf) return E_INVALIDARG;
3156 for (i = 0; i < count; i++)
3158 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
3159 properties[i].valueSize );
3160 if (hr != S_OK) return hr;
3163 if ((hr = read_init_state( reader )) != S_OK) return hr;
3165 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
3166 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
3167 &charset, sizeof(charset) );
3168 if (hr != S_OK) return hr;
3170 set_input_buffer( reader, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
3171 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
3172 read_insert_bof( reader, node );
3173 return S_OK;
3176 /**************************************************************************
3177 * WsXmlStringEquals [webservices.@]
3179 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
3181 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
3182 if (error) FIXME( "ignoring error parameter\n" );
3184 if (!str1 || !str2) return E_INVALIDARG;
3186 if (str1->length != str2->length) return S_FALSE;
3187 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
3188 return S_FALSE;