webservices: Move the reader to EOF at end of data in WsReadEndElement.
[wine.git] / dlls / webservices / reader.c
blob7abbf3cb796e4b81558ad080d701107532f92d02
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 static const struct
40 ULONG size;
41 BOOL readonly;
43 error_props[] =
45 { sizeof(ULONG), TRUE }, /* WS_ERROR_PROPERTY_STRING_COUNT */
46 { sizeof(ULONG), FALSE }, /* WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE */
47 { sizeof(LANGID), FALSE } /* WS_ERROR_PROPERTY_LANGID */
50 struct error
52 ULONG prop_count;
53 WS_ERROR_PROPERTY prop[sizeof(error_props)/sizeof(error_props[0])];
56 static struct error *alloc_error(void)
58 static const ULONG count = sizeof(error_props)/sizeof(error_props[0]);
59 struct error *ret;
60 ULONG i, size = sizeof(*ret) + count * sizeof(WS_ERROR_PROPERTY);
61 char *ptr;
63 for (i = 0; i < count; i++) size += error_props[i].size;
64 if (!(ret = heap_alloc_zero( size ))) return NULL;
66 ptr = (char *)&ret->prop[count];
67 for (i = 0; i < count; i++)
69 ret->prop[i].value = ptr;
70 ret->prop[i].valueSize = error_props[i].size;
71 ptr += ret->prop[i].valueSize;
73 ret->prop_count = count;
74 return ret;
77 static HRESULT set_error_prop( struct error *error, WS_ERROR_PROPERTY_ID id, const void *value, ULONG size )
79 if (id >= error->prop_count || size != error_props[id].size || error_props[id].readonly)
80 return E_INVALIDARG;
82 memcpy( error->prop[id].value, value, size );
83 return S_OK;
86 static HRESULT get_error_prop( struct error *error, WS_ERROR_PROPERTY_ID id, void *buf, ULONG size )
88 if (id >= error->prop_count || size != error_props[id].size)
89 return E_INVALIDARG;
91 memcpy( buf, error->prop[id].value, error->prop[id].valueSize );
92 return S_OK;
95 /**************************************************************************
96 * WsCreateError [webservices.@]
98 HRESULT WINAPI WsCreateError( const WS_ERROR_PROPERTY *properties, ULONG count, WS_ERROR **handle )
100 struct error *error;
101 LANGID langid = GetUserDefaultUILanguage();
102 HRESULT hr;
103 ULONG i;
105 TRACE( "%p %u %p\n", properties, count, handle );
107 if (!handle) return E_INVALIDARG;
108 if (!(error = alloc_error())) return E_OUTOFMEMORY;
110 set_error_prop( error, WS_ERROR_PROPERTY_LANGID, &langid, sizeof(langid) );
111 for (i = 0; i < count; i++)
113 if (properties[i].id == WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE)
115 heap_free( error );
116 return E_INVALIDARG;
118 hr = set_error_prop( error, properties[i].id, properties[i].value, properties[i].valueSize );
119 if (hr != S_OK)
121 heap_free( error );
122 return hr;
126 *handle = (WS_ERROR *)error;
127 return S_OK;
130 /**************************************************************************
131 * WsFreeError [webservices.@]
133 void WINAPI WsFreeError( WS_ERROR *handle )
135 struct error *error = (struct error *)handle;
137 TRACE( "%p\n", handle );
138 heap_free( error );
141 static const struct
143 ULONG size;
144 BOOL readonly;
146 heap_props[] =
148 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_MAX_SIZE */
149 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_TRIM_SIZE */
150 { sizeof(SIZE_T), TRUE }, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
151 { sizeof(SIZE_T), TRUE } /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
154 struct heap
156 HANDLE handle;
157 ULONG prop_count;
158 WS_HEAP_PROPERTY prop[sizeof(heap_props)/sizeof(heap_props[0])];
161 void *ws_alloc( WS_HEAP *handle, SIZE_T size )
163 struct heap *heap = (struct heap *)handle;
164 return HeapAlloc( heap->handle, 0, size );
167 static void *ws_alloc_zero( WS_HEAP *handle, SIZE_T size )
169 struct heap *heap = (struct heap *)handle;
170 return HeapAlloc( heap->handle, HEAP_ZERO_MEMORY, size );
173 void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
175 struct heap *heap = (struct heap *)handle;
176 return HeapReAlloc( heap->handle, 0, ptr, size );
179 void ws_free( WS_HEAP *handle, void *ptr )
181 struct heap *heap = (struct heap *)handle;
182 HeapFree( heap->handle, 0, ptr );
185 /**************************************************************************
186 * WsAlloc [webservices.@]
188 HRESULT WINAPI WsAlloc( WS_HEAP *handle, SIZE_T size, void **ptr, WS_ERROR *error )
190 void *mem;
192 TRACE( "%p %u %p %p\n", handle, (ULONG)size, ptr, error );
193 if (error) FIXME( "ignoring error parameter\n" );
195 if (!handle || !ptr) return E_INVALIDARG;
197 if (!(mem = ws_alloc( handle, size ))) return E_OUTOFMEMORY;
198 *ptr = mem;
199 return S_OK;
202 static struct heap *alloc_heap(void)
204 static const ULONG count = sizeof(heap_props)/sizeof(heap_props[0]);
205 struct heap *ret;
206 ULONG i, size = sizeof(*ret) + count * sizeof(WS_HEAP_PROPERTY);
207 char *ptr;
209 for (i = 0; i < count; i++) size += heap_props[i].size;
210 if (!(ret = heap_alloc_zero( size ))) return NULL;
212 ptr = (char *)&ret->prop[count];
213 for (i = 0; i < count; i++)
215 ret->prop[i].value = ptr;
216 ret->prop[i].valueSize = heap_props[i].size;
217 ptr += ret->prop[i].valueSize;
219 ret->prop_count = count;
220 return ret;
223 static HRESULT set_heap_prop( struct heap *heap, WS_HEAP_PROPERTY_ID id, const void *value, ULONG size )
225 if (id >= heap->prop_count || size != heap_props[id].size || heap_props[id].readonly)
226 return E_INVALIDARG;
228 memcpy( heap->prop[id].value, value, size );
229 return S_OK;
232 static HRESULT get_heap_prop( struct heap *heap, WS_HEAP_PROPERTY_ID id, void *buf, ULONG size )
234 if (id >= heap->prop_count || size != heap_props[id].size)
235 return E_INVALIDARG;
237 memcpy( buf, heap->prop[id].value, heap->prop[id].valueSize );
238 return S_OK;
241 /**************************************************************************
242 * WsCreateHeap [webservices.@]
244 HRESULT WINAPI WsCreateHeap( SIZE_T max_size, SIZE_T trim_size, const WS_HEAP_PROPERTY *properties,
245 ULONG count, WS_HEAP **handle, WS_ERROR *error )
247 struct heap *heap;
249 TRACE( "%u %u %p %u %p %p\n", (ULONG)max_size, (ULONG)trim_size, properties, count, handle, error );
250 if (error) FIXME( "ignoring error parameter\n" );
252 if (!handle || count) return E_INVALIDARG;
253 if (!(heap = alloc_heap())) return E_OUTOFMEMORY;
255 set_heap_prop( heap, WS_HEAP_PROPERTY_MAX_SIZE, &max_size, sizeof(max_size) );
256 set_heap_prop( heap, WS_HEAP_PROPERTY_TRIM_SIZE, &trim_size, sizeof(trim_size) );
258 if (!(heap->handle = HeapCreate( 0, 0, max_size )))
260 heap_free( heap );
261 return E_OUTOFMEMORY;
264 *handle = (WS_HEAP *)heap;
265 return S_OK;
268 /**************************************************************************
269 * WsFreeHeap [webservices.@]
271 void WINAPI WsFreeHeap( WS_HEAP *handle )
273 struct heap *heap = (struct heap *)handle;
275 TRACE( "%p\n", handle );
277 if (!heap) return;
278 HeapDestroy( heap->handle );
279 heap_free( heap );
282 struct node *alloc_node( WS_XML_NODE_TYPE type )
284 struct node *ret;
286 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
287 ret->hdr.node.nodeType = type;
288 list_init( &ret->entry );
289 list_init( &ret->children );
290 return ret;
293 void free_attribute( WS_XML_ATTRIBUTE *attr )
295 if (!attr) return;
296 heap_free( attr->prefix );
297 heap_free( attr->localName );
298 heap_free( attr->ns );
299 heap_free( attr->value );
300 heap_free( attr );
303 void free_node( struct node *node )
305 if (!node) return;
306 switch (node->hdr.node.nodeType)
308 case WS_XML_NODE_TYPE_ELEMENT:
310 WS_XML_ELEMENT_NODE *elem = &node->hdr;
311 ULONG i;
313 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
314 heap_free( elem->attributes );
315 heap_free( elem->prefix );
316 heap_free( elem->localName );
317 heap_free( elem->ns );
318 break;
320 case WS_XML_NODE_TYPE_TEXT:
322 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
323 heap_free( text->text );
324 break;
326 case WS_XML_NODE_TYPE_COMMENT:
328 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
329 heap_free( comment->value.bytes );
330 break;
332 case WS_XML_NODE_TYPE_CDATA:
333 case WS_XML_NODE_TYPE_END_CDATA:
334 case WS_XML_NODE_TYPE_END_ELEMENT:
335 case WS_XML_NODE_TYPE_EOF:
336 case WS_XML_NODE_TYPE_BOF:
337 break;
339 default:
340 ERR( "unhandled type %u\n", node->hdr.node.nodeType );
341 break;
343 heap_free( node );
346 void destroy_nodes( struct node *node )
348 struct list *ptr;
350 if (!node) return;
351 while ((ptr = list_head( &node->children )))
353 struct node *child = LIST_ENTRY( ptr, struct node, entry );
354 list_remove( &child->entry );
355 destroy_nodes( child );
357 free_node( node );
360 static const struct
362 ULONG size;
363 BOOL readonly;
365 reader_props[] =
367 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
368 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
369 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
370 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
371 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
372 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
373 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
374 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
375 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
376 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
377 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
378 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
379 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
380 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
381 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
384 enum reader_state
386 READER_STATE_INITIAL,
387 READER_STATE_BOF,
388 READER_STATE_STARTELEMENT,
389 READER_STATE_STARTATTRIBUTE,
390 READER_STATE_STARTCDATA,
391 READER_STATE_CDATA,
392 READER_STATE_TEXT,
393 READER_STATE_ENDELEMENT,
394 READER_STATE_ENDCDATA,
395 READER_STATE_COMMENT,
396 READER_STATE_EOF
399 struct reader
401 ULONG read_size;
402 ULONG read_pos;
403 const unsigned char *read_bufptr;
404 enum reader_state state;
405 struct node *root;
406 struct node *current;
407 ULONG current_attr;
408 WS_XML_READER_INPUT_TYPE input_type;
409 const unsigned char *input_data;
410 ULONG input_size;
411 ULONG prop_count;
412 WS_XML_READER_PROPERTY prop[sizeof(reader_props)/sizeof(reader_props[0])];
415 static struct reader *alloc_reader(void)
417 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
418 struct reader *ret;
419 ULONG i, size = sizeof(*ret) + count * sizeof(WS_XML_READER_PROPERTY);
420 char *ptr;
422 for (i = 0; i < count; i++) size += reader_props[i].size;
423 if (!(ret = heap_alloc_zero( size ))) return NULL;
425 ptr = (char *)&ret->prop[count];
426 for (i = 0; i < count; i++)
428 ret->prop[i].value = ptr;
429 ret->prop[i].valueSize = reader_props[i].size;
430 ptr += ret->prop[i].valueSize;
432 ret->prop_count = count;
433 return ret;
436 static HRESULT set_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID id, const void *value, ULONG size )
438 if (id >= reader->prop_count || size != reader_props[id].size || reader_props[id].readonly)
439 return E_INVALIDARG;
441 memcpy( reader->prop[id].value, value, size );
442 return S_OK;
445 static HRESULT get_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID id, void *buf, ULONG size )
447 if (id >= reader->prop_count || size != reader_props[id].size)
448 return E_INVALIDARG;
450 memcpy( buf, reader->prop[id].value, reader->prop[id].valueSize );
451 return S_OK;
454 static void read_insert_eof( struct reader *reader, struct node *eof )
456 if (!reader->root) reader->root = eof;
457 else
459 eof->parent = reader->root;
460 list_add_tail( &reader->root->children, &eof->entry );
462 reader->current = eof;
465 static void read_insert_bof( struct reader *reader, struct node *bof )
467 reader->root->parent = bof;
468 list_add_tail( &bof->children, &reader->root->entry );
469 reader->current = reader->root = bof;
472 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
474 node->parent = parent;
475 if (node->parent == reader->root)
477 struct list *eof = list_tail( &reader->root->children );
478 list_add_before( eof, &node->entry );
480 else list_add_tail( &parent->children, &node->entry );
481 reader->current = node;
484 static HRESULT read_init_state( struct reader *reader )
486 struct node *node;
488 destroy_nodes( reader->root );
489 reader->root = NULL;
490 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
491 read_insert_eof( reader, node );
492 reader->state = READER_STATE_INITIAL;
493 return S_OK;
496 /**************************************************************************
497 * WsCreateReader [webservices.@]
499 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
500 WS_XML_READER **handle, WS_ERROR *error )
502 struct reader *reader;
503 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
504 WS_CHARSET charset = WS_CHARSET_UTF8;
505 BOOL read_decl = TRUE;
506 HRESULT hr;
508 TRACE( "%p %u %p %p\n", properties, count, handle, error );
509 if (error) FIXME( "ignoring error parameter\n" );
511 if (!handle) return E_INVALIDARG;
512 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
514 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
515 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
516 set_reader_prop( reader, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
517 set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
518 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
520 for (i = 0; i < count; i++)
522 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
523 if (hr != S_OK)
525 heap_free( reader );
526 return hr;
530 if ((hr = read_init_state( reader )) != S_OK)
532 heap_free( reader );
533 return hr;
536 *handle = (WS_XML_READER *)reader;
537 return S_OK;
540 /**************************************************************************
541 * WsFreeReader [webservices.@]
543 void WINAPI WsFreeReader( WS_XML_READER *handle )
545 struct reader *reader = (struct reader *)handle;
547 TRACE( "%p\n", handle );
549 if (!reader) return;
550 destroy_nodes( reader->root );
551 heap_free( reader );
554 /**************************************************************************
555 * WsFillReader [webservices.@]
557 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
558 WS_ERROR *error )
560 struct reader *reader = (struct reader *)handle;
562 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
563 if (error) FIXME( "ignoring error parameter\n" );
565 if (!reader) return E_INVALIDARG;
567 /* FIXME: add support for stream input */
568 reader->read_size = min( min_size, reader->input_size );
569 reader->read_pos = 0;
571 return S_OK;
574 /**************************************************************************
575 * WsGetErrorProperty [webservices.@]
577 HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf,
578 ULONG size )
580 struct error *error = (struct error *)handle;
582 TRACE( "%p %u %p %u\n", handle, id, buf, size );
583 return get_error_prop( error, id, buf, size );
586 /**************************************************************************
587 * WsGetErrorString [webservices.@]
589 HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str )
591 FIXME( "%p %u %p: stub\n", handle, index, str );
592 return E_NOTIMPL;
595 /**************************************************************************
596 * WsGetHeapProperty [webservices.@]
598 HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
599 ULONG size, WS_ERROR *error )
601 struct heap *heap = (struct heap *)handle;
603 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
604 if (error) FIXME( "ignoring error parameter\n" );
606 return get_heap_prop( heap, id, buf, size );
609 /**************************************************************************
610 * WsGetNamespaceFromPrefix [webservices.@]
612 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
613 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
615 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
616 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
617 static const WS_XML_STRING empty_ns = {0, NULL};
618 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
619 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
620 struct reader *reader = (struct reader *)handle;
621 BOOL found = FALSE;
623 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
624 if (error) FIXME( "ignoring error parameter\n" );
626 if (!reader || !prefix || !ns) return E_INVALIDARG;
627 if (reader->state != READER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
629 if (!prefix->length)
631 *ns = &empty_ns;
632 found = TRUE;
634 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
636 *ns = &xml_ns;
637 found = TRUE;
639 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
641 *ns = &xmlns_ns;
642 found = TRUE;
644 else
646 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
647 ULONG i;
649 for (i = 0; i < elem->attributeCount; i++)
651 if (!elem->attributes[i]->isXmlNs) continue;
652 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
654 *ns = elem->attributes[i]->ns;
655 found = TRUE;
656 break;
661 if (!found)
663 if (required) return WS_E_INVALID_FORMAT;
664 *ns = NULL;
665 return S_FALSE;
667 return S_OK;
670 /**************************************************************************
671 * WsGetReaderNode [webservices.@]
673 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
674 WS_ERROR *error )
676 struct reader *reader = (struct reader *)handle;
678 TRACE( "%p %p %p\n", handle, node, error );
679 if (error) FIXME( "ignoring error parameter\n" );
681 if (!reader || !node) return E_INVALIDARG;
683 *node = &reader->current->hdr.node;
684 return S_OK;
687 /**************************************************************************
688 * WsGetReaderProperty [webservices.@]
690 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
691 void *buf, ULONG size, WS_ERROR *error )
693 struct reader *reader = (struct reader *)handle;
695 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
696 if (error) FIXME( "ignoring error parameter\n" );
698 if (!reader->input_type) return WS_E_INVALID_OPERATION;
700 if (id == WS_XML_READER_PROPERTY_CHARSET)
702 WS_CHARSET charset;
703 HRESULT hr;
705 if ((hr = get_reader_prop( reader, id, &charset, size )) != S_OK) return hr;
706 if (!charset) return WS_E_INVALID_FORMAT;
707 *(WS_CHARSET *)buf = charset;
708 return S_OK;
710 return get_reader_prop( reader, id, buf, size );
713 /**************************************************************************
714 * WsGetXmlAttribute [webservices.@]
716 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
717 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
719 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
720 return E_NOTIMPL;
723 WS_XML_STRING *alloc_xml_string( const unsigned char *data, ULONG len )
725 WS_XML_STRING *ret;
727 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
728 ret->length = len;
729 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
730 ret->dictionary = NULL;
731 ret->id = 0;
732 if (data) memcpy( ret->bytes, data, len );
733 return ret;
736 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *data, ULONG len )
738 WS_XML_UTF8_TEXT *ret;
740 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
741 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
742 ret->value.length = len;
743 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
744 ret->value.dictionary = NULL;
745 ret->value.id = 0;
746 if (data) memcpy( ret->value.bytes, data, len );
747 return ret;
750 static inline BOOL read_end_of_data( struct reader *reader )
752 return reader->read_pos >= reader->read_size;
755 static inline const unsigned char *read_current_ptr( struct reader *reader )
757 return &reader->read_bufptr[reader->read_pos];
760 /* UTF-8 support based on libs/wine/utf8.c */
762 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
763 static const char utf8_length[128] =
765 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
766 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
767 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
768 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
769 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
770 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
771 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
772 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
775 /* first byte mask depending on UTF-8 sequence length */
776 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
778 /* minimum Unicode value depending on UTF-8 sequence length */
779 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
781 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
783 unsigned int len, res;
784 unsigned char ch = reader->read_bufptr[reader->read_pos];
785 const unsigned char *end;
787 if (reader->read_pos >= reader->read_size) return 0;
789 if (ch < 0x80)
791 *skip = 1;
792 return ch;
794 len = utf8_length[ch - 0x80];
795 if (reader->read_pos + len >= reader->read_size) return 0;
796 end = reader->read_bufptr + reader->read_pos + len;
797 res = ch & utf8_mask[len];
799 switch (len)
801 case 3:
802 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
803 res = (res << 6) | ch;
804 case 2:
805 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
806 res = (res << 6) | ch;
807 case 1:
808 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
809 res = (res << 6) | ch;
810 if (res < utf8_minval[len]) break;
811 *skip = len + 1;
812 return res;
815 return 0;
818 static inline void read_skip( struct reader *reader, unsigned int count )
820 while (reader->read_pos < reader->read_size && count)
822 reader->read_pos++;
823 count--;
827 static inline BOOL read_isnamechar( unsigned int ch )
829 /* FIXME: incomplete */
830 return (ch >= 'A' && ch <= 'Z') ||
831 (ch >= 'a' && ch <= 'z') ||
832 (ch >= '0' && ch <= '9') ||
833 ch == '_' || ch == '-' || ch == '.' || ch == ':';
836 static inline BOOL read_isspace( unsigned int ch )
838 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
841 static inline void read_skip_whitespace( struct reader *reader )
843 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
844 reader->read_pos++;
847 static inline int read_cmp( struct reader *reader, const char *str, int len )
849 const unsigned char *ptr = read_current_ptr( reader );
851 if (len < 0) len = strlen( str );
852 if (reader->read_pos + len > reader->read_size) return -1;
853 while (len--)
855 if (*str != *ptr) return *ptr - *str;
856 str++; ptr++;
858 return 0;
861 static HRESULT read_xmldecl( struct reader *reader )
863 if (!reader->read_size) return WS_E_INVALID_FORMAT;
865 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
867 reader->state = READER_STATE_BOF;
868 return S_OK;
870 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
871 read_skip( reader, 6 );
873 /* FIXME: parse attributes */
874 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
875 reader->read_pos++;
877 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
878 read_skip( reader, 2 );
880 reader->state = READER_STATE_BOF;
881 return S_OK;
884 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
886 if (elem->attributeCount)
888 WS_XML_ATTRIBUTE **tmp;
889 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
890 return E_OUTOFMEMORY;
891 elem->attributes = tmp;
893 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
894 elem->attributes[elem->attributeCount++] = attr;
895 return S_OK;
898 static HRESULT parse_name( const unsigned char *str, unsigned int len,
899 WS_XML_STRING **prefix, WS_XML_STRING **localname )
901 const unsigned char *name_ptr = str, *prefix_ptr = NULL;
902 unsigned int i, name_len = len, prefix_len = 0;
904 for (i = 0; i < len; i++)
906 if (str[i] == ':')
908 prefix_ptr = str;
909 prefix_len = i;
910 name_ptr = &str[i + 1];
911 name_len -= i + 1;
912 break;
915 if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
916 if (!(*localname = alloc_xml_string( name_ptr, name_len )))
918 heap_free( *prefix );
919 return E_OUTOFMEMORY;
921 return S_OK;
924 static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
926 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
927 WS_XML_ATTRIBUTE *attr;
928 WS_XML_UTF8_TEXT *text;
929 unsigned int len = 0, ch, skip, quote;
930 const unsigned char *start;
931 WS_XML_STRING *prefix, *localname;
932 HRESULT hr = WS_E_INVALID_FORMAT;
934 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
936 start = read_current_ptr( reader );
937 for (;;)
939 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
940 if (!read_isnamechar( ch )) break;
941 read_skip( reader, skip );
942 len += skip;
944 if (!len) goto error;
946 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) goto error;
947 hr = E_OUTOFMEMORY;
948 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
950 attr->isXmlNs = 1;
951 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length ))) goto error;
952 attr->localName = localname;
954 else
956 attr->prefix = prefix;
957 attr->localName = localname;
960 hr = WS_E_INVALID_FORMAT;
961 read_skip_whitespace( reader );
962 if (read_cmp( reader, "=", 1 )) goto error;
963 read_skip( reader, 1 );
965 read_skip_whitespace( reader );
966 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) goto error;
967 quote = read_utf8_char( reader, &skip );
968 read_skip( reader, 1 );
970 len = 0;
971 start = read_current_ptr( reader );
972 for (;;)
974 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
975 if (ch == quote) break;
976 read_skip( reader, skip );
977 len += skip;
979 read_skip( reader, 1 );
981 hr = E_OUTOFMEMORY;
982 if (attr->isXmlNs)
984 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
985 if (!(text = alloc_utf8_text( NULL, 0 ))) goto error;
986 attr->value = &text->text;
988 else
990 if (!(attr->ns = alloc_xml_string( NULL, 0 ))) goto error;
991 if (!(text = alloc_utf8_text( start, len ))) goto error;
992 attr->value = &text->text;
994 attr->singleQuote = (quote == '\'');
996 *ret = attr;
997 return S_OK;
999 error:
1000 free_attribute( attr );
1001 return hr;
1004 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
1006 ULONG i;
1007 if (len1 != len2) return 1;
1008 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
1009 return 0;
1012 static struct node *read_find_parent( struct reader *reader, const WS_XML_STRING *prefix,
1013 const WS_XML_STRING *localname )
1015 struct node *parent;
1016 const WS_XML_STRING *str;
1018 for (parent = reader->current; parent; parent = parent->parent)
1020 if (parent->hdr.node.nodeType == WS_XML_NODE_TYPE_BOF)
1022 if (!localname) return parent;
1023 return NULL;
1025 else if (parent->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1027 if (!localname) return parent;
1029 str = parent->hdr.prefix;
1030 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
1031 str = parent->hdr.localName;
1032 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
1033 return parent;
1037 return NULL;
1040 static HRESULT read_element( struct reader *reader )
1042 unsigned int len = 0, ch, skip;
1043 const unsigned char *start;
1044 struct node *node = NULL, *parent;
1045 WS_XML_ELEMENT_NODE *elem;
1046 WS_XML_ATTRIBUTE *attr;
1047 HRESULT hr = WS_E_INVALID_FORMAT;
1049 if (read_end_of_data( reader ))
1051 struct list *eof = list_tail( &reader->root->children );
1052 reader->current = LIST_ENTRY( eof, struct node, entry );
1053 reader->state = READER_STATE_EOF;
1054 return S_OK;
1057 if (read_cmp( reader, "<", 1 )) goto error;
1058 read_skip( reader, 1 );
1060 start = read_current_ptr( reader );
1061 for (;;)
1063 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1064 if (!read_isnamechar( ch )) break;
1065 read_skip( reader, skip );
1066 len += skip;
1068 if (!len) goto error;
1070 if (!(parent = read_find_parent( reader, NULL, NULL ))) goto error;
1072 hr = E_OUTOFMEMORY;
1073 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error;
1074 elem = (WS_XML_ELEMENT_NODE *)node;
1076 if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1077 hr = E_OUTOFMEMORY;
1078 if (!(elem->ns = alloc_xml_string( NULL, 0 ))) goto error;
1079 elem->ns->bytes = (BYTE *)(elem->ns + 1);
1081 reader->current_attr = 0;
1082 for (;;)
1084 read_skip_whitespace( reader );
1085 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1086 if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
1087 if ((hr = append_attribute( elem, attr )) != S_OK)
1089 free_attribute( attr );
1090 goto error;
1092 reader->current_attr++;
1095 read_insert_node( reader, parent, node );
1096 reader->state = READER_STATE_STARTELEMENT;
1097 return S_OK;
1099 error:
1100 free_node( node );
1101 return hr;
1104 static HRESULT read_text( struct reader *reader )
1106 unsigned int len = 0, ch, skip;
1107 const unsigned char *start;
1108 struct node *node;
1109 WS_XML_TEXT_NODE *text;
1110 WS_XML_UTF8_TEXT *utf8;
1112 start = read_current_ptr( reader );
1113 for (;;)
1115 if (read_end_of_data( reader )) break;
1116 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1117 if (ch == '<') break;
1118 read_skip( reader, skip );
1119 len += skip;
1122 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1123 text = (WS_XML_TEXT_NODE *)node;
1124 if (!(utf8 = alloc_utf8_text( start, len )))
1126 heap_free( node );
1127 return E_OUTOFMEMORY;
1129 text->text = &utf8->text;
1131 read_insert_node( reader, reader->current, node );
1132 reader->state = READER_STATE_TEXT;
1133 return S_OK;
1136 static HRESULT read_node( struct reader * );
1138 static HRESULT read_startelement( struct reader *reader )
1140 struct node *node;
1142 read_skip_whitespace( reader );
1143 if (!read_cmp( reader, "/>", 2 ))
1145 read_skip( reader, 2 );
1146 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1147 read_insert_node( reader, reader->current, node );
1148 reader->state = READER_STATE_ENDELEMENT;
1149 return S_OK;
1151 else if (!read_cmp( reader, ">", 1 ))
1153 read_skip( reader, 1 );
1154 return read_node( reader );
1156 return WS_E_INVALID_FORMAT;
1159 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
1161 HRESULT hr;
1163 switch (reader->state)
1165 case READER_STATE_INITIAL:
1166 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
1167 break;
1169 case READER_STATE_STARTELEMENT:
1170 if (found) *found = TRUE;
1171 return S_OK;
1173 default:
1174 break;
1177 read_skip_whitespace( reader );
1178 if ((hr = read_element( reader )) == S_OK && found)
1180 if (reader->state == READER_STATE_STARTELEMENT)
1181 *found = TRUE;
1182 else
1183 *found = FALSE;
1186 return hr;
1189 static HRESULT read_endelement( struct reader *reader )
1191 struct node *node, *parent;
1192 unsigned int len = 0, ch, skip;
1193 const unsigned char *start;
1194 WS_XML_STRING *prefix, *localname;
1195 HRESULT hr;
1197 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
1199 if (read_end_of_data( reader ))
1201 struct list *eof = list_tail( &reader->root->children );
1202 reader->current = LIST_ENTRY( eof, struct node, entry );
1203 reader->state = READER_STATE_EOF;
1204 return S_OK;
1207 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
1208 read_skip( reader, 2 );
1210 start = read_current_ptr( reader );
1211 for (;;)
1213 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1214 if (ch == '>')
1216 read_skip( reader, 1 );
1217 break;
1219 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
1220 read_skip( reader, skip );
1221 len += skip;
1224 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
1225 parent = read_find_parent( reader, prefix, localname );
1226 heap_free( prefix );
1227 heap_free( localname );
1228 if (!parent) return WS_E_INVALID_FORMAT;
1230 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1231 read_insert_node( reader, parent, node );
1232 reader->state = READER_STATE_ENDELEMENT;
1233 return S_OK;
1236 static HRESULT read_comment( struct reader *reader )
1238 unsigned int len = 0, ch, skip;
1239 const unsigned char *start;
1240 struct node *node;
1241 WS_XML_COMMENT_NODE *comment;
1243 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
1244 read_skip( reader, 4 );
1246 start = read_current_ptr( reader );
1247 for (;;)
1249 if (!read_cmp( reader, "-->", 3 ))
1251 read_skip( reader, 3 );
1252 break;
1254 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1255 read_skip( reader, skip );
1256 len += skip;
1259 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
1260 comment = (WS_XML_COMMENT_NODE *)node;
1261 if (!(comment->value.bytes = heap_alloc( len )))
1263 heap_free( node );
1264 return E_OUTOFMEMORY;
1266 memcpy( comment->value.bytes, start, len );
1267 comment->value.length = len;
1269 read_insert_node( reader, reader->current, node );
1270 reader->state = READER_STATE_COMMENT;
1271 return S_OK;
1274 static HRESULT read_startcdata( struct reader *reader )
1276 struct node *node;
1278 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
1279 read_skip( reader, 9 );
1281 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
1282 read_insert_node( reader, reader->current, node );
1283 reader->state = READER_STATE_STARTCDATA;
1284 return S_OK;
1287 static HRESULT read_cdata( struct reader *reader )
1289 unsigned int len = 0, ch, skip;
1290 const unsigned char *start;
1291 struct node *node;
1292 WS_XML_TEXT_NODE *text;
1293 WS_XML_UTF8_TEXT *utf8;
1295 start = read_current_ptr( reader );
1296 for (;;)
1298 if (!read_cmp( reader, "]]>", 3 )) break;
1299 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1300 read_skip( reader, skip );
1301 len += skip;
1304 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1305 text = (WS_XML_TEXT_NODE *)node;
1306 if (!(utf8 = alloc_utf8_text( start, len )))
1308 heap_free( node );
1309 return E_OUTOFMEMORY;
1311 text->text = &utf8->text;
1313 read_insert_node( reader, reader->current, node );
1314 reader->state = READER_STATE_CDATA;
1315 return S_OK;
1318 static HRESULT read_endcdata( struct reader *reader )
1320 struct node *node;
1322 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
1323 read_skip( reader, 3 );
1325 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_CDATA ))) return E_OUTOFMEMORY;
1326 read_insert_node( reader, reader->current->parent, node );
1327 reader->state = READER_STATE_ENDCDATA;
1328 return S_OK;
1331 static HRESULT read_node( struct reader *reader )
1333 HRESULT hr;
1335 for (;;)
1337 if (read_end_of_data( reader ))
1339 struct list *eof = list_tail( &reader->root->children );
1340 reader->current = LIST_ENTRY( eof, struct node, entry );
1341 reader->state = READER_STATE_EOF;
1342 return S_OK;
1344 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
1345 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
1346 else if (!read_cmp( reader, "<?", 2 ))
1348 hr = read_xmldecl( reader );
1349 if (FAILED( hr )) return hr;
1351 else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
1352 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
1353 else if (!read_cmp( reader, "<!--", 4 )) return read_comment( reader );
1354 else if (!read_cmp( reader, "<", 1 )) return read_element( reader );
1355 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement( reader );
1356 else return read_text( reader );
1360 /**************************************************************************
1361 * WsReadEndElement [webservices.@]
1363 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
1365 struct reader *reader = (struct reader *)handle;
1367 TRACE( "%p %p\n", handle, error );
1368 if (error) FIXME( "ignoring error parameter\n" );
1370 if (!reader) return E_INVALIDARG;
1371 return read_endelement( reader );
1374 /**************************************************************************
1375 * WsReadNode [webservices.@]
1377 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
1379 struct reader *reader = (struct reader *)handle;
1381 TRACE( "%p %p\n", handle, error );
1382 if (error) FIXME( "ignoring error parameter\n" );
1384 if (!reader) return E_INVALIDARG;
1385 return read_node( reader );
1388 /**************************************************************************
1389 * WsReadStartElement [webservices.@]
1391 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
1393 struct reader *reader = (struct reader *)handle;
1395 TRACE( "%p %p\n", handle, error );
1396 if (error) FIXME( "ignoring error parameter\n" );
1398 if (!reader) return E_INVALIDARG;
1399 return read_startelement( reader );
1402 /**************************************************************************
1403 * WsReadToStartElement [webservices.@]
1405 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
1406 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
1408 struct reader *reader = (struct reader *)handle;
1410 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
1411 if (error) FIXME( "ignoring error parameter\n" );
1413 if (!reader) return E_INVALIDARG;
1414 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
1416 return read_to_startelement( reader, found );
1419 static BOOL move_to_root_element( struct reader *reader )
1421 struct list *ptr;
1422 struct node *node;
1424 if (!(ptr = list_head( &reader->root->children ))) return FALSE;
1425 node = LIST_ENTRY( ptr, struct node, entry );
1426 if (node->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1428 reader->current = node;
1429 return TRUE;
1431 while ((ptr = list_next( &reader->root->children, &node->entry )))
1433 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1434 if (next->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1436 reader->current = next;
1437 return TRUE;
1439 node = next;
1441 return FALSE;
1444 static BOOL move_to_next_element( struct reader *reader )
1446 struct list *ptr;
1447 struct node *node = reader->current;
1449 while ((ptr = list_next( &node->parent->children, &node->entry )))
1451 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1452 if (next->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1454 reader->current = next;
1455 return TRUE;
1457 node = next;
1459 return FALSE;
1462 static BOOL move_to_prev_element( struct reader *reader )
1464 struct list *ptr;
1465 struct node *node = reader->current;
1467 while ((ptr = list_prev( &node->parent->children, &node->entry )))
1469 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
1470 if (prev->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1472 reader->current = prev;
1473 return TRUE;
1475 node = prev;
1477 return FALSE;
1480 static BOOL move_to_child_element( struct reader *reader )
1482 struct list *ptr;
1483 struct node *node;
1485 if (!(ptr = list_head( &reader->current->children ))) return FALSE;
1486 node = LIST_ENTRY( ptr, struct node, entry );
1487 if (node->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1489 reader->current = node;
1490 return TRUE;
1492 while ((ptr = list_next( &reader->current->children, &node->entry )))
1494 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1495 if (next->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1497 reader->current = next;
1498 return TRUE;
1500 node = next;
1502 return FALSE;
1505 static BOOL move_to_end_element( struct reader *reader )
1507 struct list *ptr;
1508 struct node *node = reader->current;
1510 if (node->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
1512 if ((ptr = list_tail( &node->children )))
1514 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
1515 if (tail->hdr.node.nodeType == WS_XML_NODE_TYPE_END_ELEMENT)
1517 reader->current = tail;
1518 return TRUE;
1521 return FALSE;
1524 static BOOL move_to_parent_element( struct reader *reader )
1526 struct node *parent = reader->current->parent;
1528 if (parent && (parent->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT ||
1529 parent->hdr.node.nodeType == WS_XML_NODE_TYPE_BOF))
1531 reader->current = parent;
1532 return TRUE;
1534 return FALSE;
1537 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
1539 struct list *ptr;
1540 BOOL success = FALSE;
1541 HRESULT hr = S_OK;
1543 if (!read_end_of_data( reader ))
1545 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
1546 if (hr != S_OK) return hr;
1548 switch (move)
1550 case WS_MOVE_TO_ROOT_ELEMENT:
1551 success = move_to_root_element( reader );
1552 break;
1554 case WS_MOVE_TO_NEXT_ELEMENT:
1555 success = move_to_next_element( reader );
1556 break;
1558 case WS_MOVE_TO_PREVIOUS_ELEMENT:
1559 success = move_to_prev_element( reader );
1560 break;
1562 case WS_MOVE_TO_CHILD_ELEMENT:
1563 success = move_to_child_element( reader );
1564 break;
1566 case WS_MOVE_TO_END_ELEMENT:
1567 success = move_to_end_element( reader );
1568 break;
1570 case WS_MOVE_TO_PARENT_ELEMENT:
1571 success = move_to_parent_element( reader );
1572 break;
1574 case WS_MOVE_TO_FIRST_NODE:
1575 if ((ptr = list_head( &reader->current->parent->children )))
1577 reader->current = LIST_ENTRY( ptr, struct node, entry );
1578 success = TRUE;
1580 break;
1582 case WS_MOVE_TO_NEXT_NODE:
1583 if ((ptr = list_next( &reader->current->parent->children, &reader->current->entry )))
1585 reader->current = LIST_ENTRY( ptr, struct node, entry );
1586 success = TRUE;
1588 break;
1590 case WS_MOVE_TO_PREVIOUS_NODE:
1591 if ((ptr = list_prev( &reader->current->parent->children, &reader->current->entry )))
1593 reader->current = LIST_ENTRY( ptr, struct node, entry );
1594 success = TRUE;
1596 break;
1598 case WS_MOVE_TO_CHILD_NODE:
1599 if ((ptr = list_head( &reader->current->children )))
1601 reader->current = LIST_ENTRY( ptr, struct node, entry );
1602 success = TRUE;
1604 break;
1606 case WS_MOVE_TO_BOF:
1607 reader->current = reader->root;
1608 success = TRUE;
1609 break;
1611 case WS_MOVE_TO_EOF:
1612 if ((ptr = list_tail( &reader->root->children )))
1614 reader->current = LIST_ENTRY( ptr, struct node, entry );
1615 success = TRUE;
1617 break;
1619 default:
1620 FIXME( "unhandled move %u\n", move );
1621 return E_NOTIMPL;
1624 if (found)
1626 *found = success;
1627 return S_OK;
1629 return success ? S_OK : WS_E_INVALID_FORMAT;
1632 /**************************************************************************
1633 * WsMoveReader [webservices.@]
1635 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
1637 struct reader *reader = (struct reader *)handle;
1639 TRACE( "%p %u %p %p\n", handle, move, found, error );
1640 if (error) FIXME( "ignoring error parameter\n" );
1642 if (!reader) return E_INVALIDARG;
1643 if (!reader->input_type) return WS_E_INVALID_OPERATION;
1645 return read_move_to( reader, move, found );
1648 /**************************************************************************
1649 * WsReadStartAttribute [webservices.@]
1651 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
1653 struct reader *reader = (struct reader *)handle;
1654 WS_XML_ELEMENT_NODE *elem;
1656 TRACE( "%p %u %p\n", handle, index, error );
1657 if (error) FIXME( "ignoring error parameter\n" );
1659 if (!reader) return E_INVALIDARG;
1661 elem = &reader->current->hdr;
1662 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
1663 return WS_E_INVALID_FORMAT;
1665 reader->current_attr = index;
1666 reader->state = READER_STATE_STARTATTRIBUTE;
1667 return S_OK;
1670 /**************************************************************************
1671 * WsReadEndAttribute [webservices.@]
1673 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
1675 struct reader *reader = (struct reader *)handle;
1677 TRACE( "%p %p\n", handle, error );
1678 if (error) FIXME( "ignoring error parameter\n" );
1680 if (!reader) return E_INVALIDARG;
1682 if (reader->state != READER_STATE_STARTATTRIBUTE)
1683 return WS_E_INVALID_FORMAT;
1685 reader->state = READER_STATE_STARTELEMENT;
1686 return S_OK;
1689 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
1691 WCHAR *ret;
1693 switch (text->textType)
1695 case WS_XML_TEXT_TYPE_UTF8:
1697 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
1698 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
1699 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
1700 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
1701 ret[len] = 0;
1702 break;
1704 default:
1705 FIXME( "unhandled type %u\n", text->textType );
1706 return NULL;
1709 return ret;
1712 #define MAX_INT8 0x7f
1713 #define MIN_INT8 (-MAX_INT8 - 1)
1714 #define MAX_INT16 0x7fff
1715 #define MIN_INT16 (-MAX_INT16 - 1)
1716 #define MAX_INT32 0x7fffffff
1717 #define MIN_INT32 (-MAX_INT32 - 1)
1718 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1719 #define MIN_INT64 (-MAX_INT64 - 1)
1720 #define MAX_UINT8 0xff
1721 #define MAX_UINT16 0xffff
1722 #define MAX_UINT32 0xffffffff
1723 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1725 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
1727 BOOL negative = FALSE;
1728 const unsigned char *ptr = str;
1730 *ret = 0;
1731 while (len && read_isspace( *ptr )) { ptr++; len--; }
1732 while (len && read_isspace( ptr[len - 1] )) { len--; }
1733 if (!len) return WS_E_INVALID_FORMAT;
1735 if (*ptr == '-')
1737 negative = TRUE;
1738 ptr++;
1739 len--;
1741 if (!len) return WS_E_INVALID_FORMAT;
1743 while (len--)
1745 int val;
1747 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1748 val = *ptr - '0';
1749 if (negative) val = -val;
1751 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
1752 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
1754 return WS_E_NUMERIC_OVERFLOW;
1756 *ret = *ret * 10 + val;
1757 ptr++;
1760 return S_OK;
1763 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
1765 const unsigned char *ptr = str;
1767 *ret = 0;
1768 while (len && read_isspace( *ptr )) { ptr++; len--; }
1769 while (len && read_isspace( ptr[len - 1] )) { len--; }
1770 if (!len) return WS_E_INVALID_FORMAT;
1772 while (len--)
1774 unsigned int val;
1776 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1777 val = *ptr - '0';
1779 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
1780 *ret = *ret * 10 + val;
1781 ptr++;
1784 return S_OK;
1787 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
1789 WS_XML_TEXT_NODE *text;
1791 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_TEXT)
1792 return WS_E_INVALID_FORMAT;
1794 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
1795 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
1797 FIXME( "text type %u not supported\n", text->text->textType );
1798 return E_NOTIMPL;
1800 *ret = (WS_XML_UTF8_TEXT *)text->text;
1801 return S_OK;
1804 static HRESULT read_get_attribute_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
1806 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1807 WS_XML_ATTRIBUTE *attr;
1809 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT ||
1810 reader->current_attr >= elem->attributeCount) return WS_E_INVALID_FORMAT;
1812 attr = elem->attributes[reader->current_attr];
1813 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
1815 FIXME( "text type %u not supported\n", attr->value->textType );
1816 return E_NOTIMPL;
1818 *ret = (WS_XML_UTF8_TEXT *)attr->value;
1819 reader->current_attr++;
1820 return S_OK;
1823 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
1824 const WS_XML_STRING *ns, ULONG *index )
1826 ULONG i;
1827 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1829 if (!localname)
1831 *index = reader->current_attr;
1832 return TRUE;
1834 for (i = 0; i < elem->attributeCount; i++)
1836 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
1837 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
1839 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
1840 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
1842 *index = i;
1843 return TRUE;
1846 return FALSE;
1849 /**************************************************************************
1850 * WsFindAttribute [webservices.@]
1852 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
1853 const WS_XML_STRING *ns, BOOL required, ULONG *index,
1854 WS_ERROR *error )
1856 struct reader *reader = (struct reader *)handle;
1858 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
1859 required, index, error );
1860 if (error) FIXME( "ignoring error parameter\n" );
1862 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
1864 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT)
1865 return WS_E_INVALID_OPERATION;
1867 if (!find_attribute( reader, localname, ns, index ))
1869 if (required) return WS_E_INVALID_FORMAT;
1870 *index = ~0u;
1871 return S_FALSE;
1873 return S_OK;
1876 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
1877 const WS_BOOL_DESCRIPTION *desc, BOOL *ret )
1879 WS_XML_UTF8_TEXT *utf8;
1880 HRESULT hr;
1881 ULONG len;
1883 if (desc)
1885 FIXME( "description not supported\n" );
1886 return E_NOTIMPL;
1888 switch (mapping)
1890 case WS_ATTRIBUTE_TYPE_MAPPING:
1891 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1892 len = utf8->value.length;
1893 break;
1895 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1896 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1897 len = utf8->value.length;
1898 break;
1900 default:
1901 FIXME( "mapping %u not supported\n", mapping );
1902 return E_NOTIMPL;
1905 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) *ret = TRUE;
1906 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) *ret = TRUE;
1907 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) *ret = FALSE;
1908 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) *ret = FALSE;
1909 else return WS_E_INVALID_FORMAT;
1911 return S_OK;
1914 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
1915 const WS_INT8_DESCRIPTION *desc, INT8 *ret )
1917 WS_XML_UTF8_TEXT *utf8;
1918 HRESULT hr;
1919 INT64 val;
1921 if (desc)
1923 FIXME( "description not supported\n" );
1924 return E_NOTIMPL;
1926 switch (mapping)
1928 case WS_ATTRIBUTE_TYPE_MAPPING:
1929 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1930 break;
1932 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1933 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1934 break;
1936 default:
1937 FIXME( "mapping %u not supported\n", mapping );
1938 return E_NOTIMPL;
1941 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
1942 return hr;
1944 *ret = val;
1945 return S_OK;
1948 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
1949 const WS_INT16_DESCRIPTION *desc, INT16 *ret )
1951 WS_XML_UTF8_TEXT *utf8;
1952 HRESULT hr;
1953 INT64 val;
1955 if (desc)
1957 FIXME( "description not supported\n" );
1958 return E_NOTIMPL;
1960 switch (mapping)
1962 case WS_ATTRIBUTE_TYPE_MAPPING:
1963 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1964 break;
1966 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1967 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1968 break;
1970 default:
1971 FIXME( "mapping %u not supported\n", mapping );
1972 return E_NOTIMPL;
1975 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
1976 return hr;
1978 *ret = val;
1979 return S_OK;
1982 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
1983 const WS_INT32_DESCRIPTION *desc, INT32 *ret )
1985 WS_XML_UTF8_TEXT *utf8;
1986 HRESULT hr;
1987 INT64 val;
1989 if (desc)
1991 FIXME( "description not supported\n" );
1992 return E_NOTIMPL;
1994 switch (mapping)
1996 case WS_ATTRIBUTE_TYPE_MAPPING:
1997 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1998 break;
2000 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2001 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2002 break;
2004 default:
2005 FIXME( "mapping %u not supported\n", mapping );
2006 return E_NOTIMPL;
2009 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
2010 return hr;
2012 *ret = val;
2013 return S_OK;
2016 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
2017 const WS_INT64_DESCRIPTION *desc, INT64 *ret )
2019 WS_XML_UTF8_TEXT *utf8;
2020 HRESULT hr;
2021 INT64 val;
2023 if (desc)
2025 FIXME( "description not supported\n" );
2026 return E_NOTIMPL;
2028 switch (mapping)
2030 case WS_ATTRIBUTE_TYPE_MAPPING:
2031 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
2032 break;
2034 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2035 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2036 break;
2038 default:
2039 FIXME( "mapping %u not supported\n", mapping );
2040 return E_NOTIMPL;
2043 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
2044 return hr;
2046 *ret = val;
2047 return S_OK;
2050 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
2051 const WS_UINT8_DESCRIPTION *desc, UINT8 *ret )
2053 WS_XML_UTF8_TEXT *utf8;
2054 HRESULT hr;
2055 UINT64 val;
2057 if (desc)
2059 FIXME( "description not supported\n" );
2060 return E_NOTIMPL;
2062 switch (mapping)
2064 case WS_ATTRIBUTE_TYPE_MAPPING:
2065 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
2066 break;
2068 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2069 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2070 break;
2072 default:
2073 FIXME( "mapping %u not supported\n", mapping );
2074 return E_NOTIMPL;
2077 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
2078 return hr;
2080 *ret = val;
2081 return S_OK;
2084 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
2085 const WS_UINT16_DESCRIPTION *desc, UINT16 *ret )
2087 WS_XML_UTF8_TEXT *utf8;
2088 HRESULT hr;
2089 UINT64 val;
2091 if (desc)
2093 FIXME( "description not supported\n" );
2094 return E_NOTIMPL;
2096 switch (mapping)
2098 case WS_ATTRIBUTE_TYPE_MAPPING:
2099 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
2100 break;
2102 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2103 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2104 break;
2106 default:
2107 FIXME( "mapping %u not supported\n", mapping );
2108 return E_NOTIMPL;
2111 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
2112 return hr;
2114 *ret = val;
2115 return S_OK;
2118 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
2119 const WS_UINT32_DESCRIPTION *desc, UINT32 *ret )
2121 WS_XML_UTF8_TEXT *utf8;
2122 HRESULT hr;
2123 UINT64 val;
2125 if (desc)
2127 FIXME( "description not supported\n" );
2128 return E_NOTIMPL;
2130 switch (mapping)
2132 case WS_ATTRIBUTE_TYPE_MAPPING:
2133 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
2134 break;
2136 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2137 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2138 break;
2140 default:
2141 FIXME( "mapping %u not supported\n", mapping );
2142 return E_NOTIMPL;
2145 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
2146 return hr;
2148 *ret = val;
2149 return S_OK;
2152 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
2153 const WS_UINT64_DESCRIPTION *desc, UINT64 *ret )
2155 WS_XML_UTF8_TEXT *utf8;
2156 HRESULT hr;
2157 UINT64 val;
2159 if (desc)
2161 FIXME( "description not supported\n" );
2162 return E_NOTIMPL;
2164 switch (mapping)
2166 case WS_ATTRIBUTE_TYPE_MAPPING:
2167 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
2168 break;
2170 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2171 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2172 break;
2174 default:
2175 FIXME( "mapping %u not supported\n", mapping );
2176 return E_NOTIMPL;
2179 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
2180 return hr;
2182 *ret = val;
2183 return S_OK;
2186 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
2187 const WS_WSZ_DESCRIPTION *desc, WS_HEAP *heap, WCHAR **ret )
2189 WS_XML_UTF8_TEXT *utf8;
2190 HRESULT hr;
2191 WCHAR *str;
2193 if (desc)
2195 FIXME( "description not supported\n" );
2196 return E_NOTIMPL;
2198 switch (mapping)
2200 case WS_ATTRIBUTE_TYPE_MAPPING:
2201 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
2202 break;
2204 case WS_ELEMENT_TYPE_MAPPING:
2205 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2206 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2207 break;
2209 default:
2210 FIXME( "mapping %u not supported\n", mapping );
2211 return E_NOTIMPL;
2214 if (!(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
2215 *ret = str;
2216 return S_OK;
2219 static HRESULT read_type_struct( struct reader *, WS_TYPE_MAPPING, const WS_STRUCT_DESCRIPTION *,
2220 WS_HEAP *, void ** );
2222 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
2223 WS_HEAP *heap, char *buf )
2225 char *ptr = buf + desc->offset;
2226 WS_TYPE_MAPPING mapping;
2227 HRESULT hr;
2229 if (desc->options && desc->options != WS_FIELD_POINTER &&
2230 desc->options != WS_FIELD_OPTIONAL &&
2231 desc->options != (WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
2233 FIXME( "options 0x%x not supported\n", desc->options );
2234 return E_NOTIMPL;
2237 switch (desc->mapping)
2239 case WS_ATTRIBUTE_FIELD_MAPPING:
2240 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
2241 break;
2243 case WS_ELEMENT_FIELD_MAPPING:
2244 mapping = WS_ELEMENT_TYPE_MAPPING;
2245 break;
2247 default:
2248 FIXME( "unhandled field mapping %u\n", desc->mapping );
2249 return E_NOTIMPL;
2252 switch (desc->type)
2254 case WS_STRUCT_TYPE:
2255 hr = read_type_struct( reader, mapping, desc->typeDescription, heap, (void **)ptr );
2256 break;
2258 case WS_BOOL_TYPE:
2259 hr = read_type_bool( reader, mapping, desc->typeDescription, (BOOL *)ptr );
2260 break;
2262 case WS_INT8_TYPE:
2263 hr = read_type_int8( reader, mapping, desc->typeDescription, (INT8 *)ptr );
2264 break;
2266 case WS_INT16_TYPE:
2267 hr = read_type_int16( reader, mapping, desc->typeDescription, (INT16 *)ptr );
2268 break;
2270 case WS_INT32_TYPE:
2271 hr = read_type_int32( reader, mapping, desc->typeDescription, (INT32 *)ptr );
2272 break;
2274 case WS_INT64_TYPE:
2275 hr = read_type_int64( reader, mapping, desc->typeDescription, (INT64 *)ptr );
2276 break;
2278 case WS_UINT8_TYPE:
2279 hr = read_type_uint8( reader, mapping, desc->typeDescription, (UINT8 *)ptr );
2280 break;
2282 case WS_UINT16_TYPE:
2283 hr = read_type_uint16( reader, mapping, desc->typeDescription, (UINT16 *)ptr );
2284 break;
2286 case WS_UINT32_TYPE:
2287 hr = read_type_uint32( reader, mapping, desc->typeDescription, (UINT32 *)ptr );
2288 break;
2290 case WS_UINT64_TYPE:
2291 hr = read_type_uint64( reader, mapping, desc->typeDescription, (UINT64 *)ptr );
2292 break;
2294 case WS_WSZ_TYPE:
2295 hr = read_type_wsz( reader, mapping, desc->typeDescription, heap, (WCHAR **)ptr );
2296 break;
2298 default:
2299 FIXME( "type %u not implemented\n", desc->type );
2300 return E_NOTIMPL;
2303 return hr;
2306 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
2307 const WS_STRUCT_DESCRIPTION *desc, WS_HEAP *heap, void **ret )
2309 ULONG i;
2310 HRESULT hr;
2311 char *buf;
2313 if (!desc) return E_INVALIDARG;
2315 if (desc->structOptions)
2317 FIXME( "struct options 0x%x not supported\n", desc->structOptions );
2318 return E_NOTIMPL;
2321 switch (mapping)
2323 case WS_ELEMENT_TYPE_MAPPING:
2324 if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
2325 break;
2327 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2328 if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
2329 if ((hr = read_startelement( reader )) != S_OK) return hr;
2330 break;
2332 default:
2333 FIXME( "unhandled mapping %u\n", mapping );
2334 return E_NOTIMPL;
2337 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
2339 for (i = 0; i < desc->fieldCount; i++)
2341 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
2343 ws_free( heap, buf );
2344 return hr;
2348 switch (mapping)
2350 case WS_ELEMENT_TYPE_MAPPING:
2351 if ((hr = read_endelement( reader )) != S_OK) return hr;
2352 break;
2354 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2355 if ((hr = read_endelement( reader )) != S_OK) return hr;
2356 if ((hr = read_node( reader )) != S_OK) return hr;
2357 if (reader->state != READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2358 break;
2360 default: break;
2363 *ret = buf;
2364 return S_OK;
2367 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
2368 const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
2369 void *value, ULONG size )
2371 switch (type)
2373 case WS_STRUCT_TYPE:
2375 void **ptr = value;
2376 if (option != WS_READ_REQUIRED_POINTER || size != sizeof(*ptr))
2377 return E_INVALIDARG;
2379 return read_type_struct( reader, mapping, desc, heap, ptr );
2381 case WS_BOOL_TYPE:
2383 BOOL *ptr = value;
2384 if (option != WS_READ_REQUIRED_VALUE)
2386 FIXME( "read option %u not supported\n", option );
2387 return E_NOTIMPL;
2389 if (size != sizeof(*ptr)) return E_INVALIDARG;
2390 return read_type_bool( reader, mapping, desc, ptr );
2392 case WS_INT8_TYPE:
2394 INT8 *ptr = value;
2395 if (option != WS_READ_REQUIRED_VALUE)
2397 FIXME( "read option %u not supported\n", option );
2398 return E_NOTIMPL;
2400 if (size != sizeof(*ptr)) return E_INVALIDARG;
2401 return read_type_int8( reader, mapping, desc, ptr );
2403 case WS_INT16_TYPE:
2405 INT16 *ptr = value;
2406 if (option != WS_READ_REQUIRED_VALUE)
2408 FIXME( "read option %u not supported\n", option );
2409 return E_NOTIMPL;
2411 if (size != sizeof(*ptr)) return E_INVALIDARG;
2412 return read_type_int16( reader, mapping, desc, ptr );
2414 case WS_INT32_TYPE:
2416 INT32 *ptr = value;
2417 if (option != WS_READ_REQUIRED_VALUE)
2419 FIXME( "read option %u not supported\n", option );
2420 return E_NOTIMPL;
2422 if (size != sizeof(*ptr)) return E_INVALIDARG;
2423 return read_type_int32( reader, mapping, desc, ptr );
2425 case WS_INT64_TYPE:
2427 INT64 *ptr = value;
2428 if (option != WS_READ_REQUIRED_VALUE)
2430 FIXME( "read option %u not supported\n", option );
2431 return E_NOTIMPL;
2433 if (size != sizeof(*ptr)) return E_INVALIDARG;
2434 return read_type_int64( reader, mapping, desc, ptr );
2436 case WS_UINT8_TYPE:
2438 UINT8 *ptr = value;
2439 if (option != WS_READ_REQUIRED_VALUE)
2441 FIXME( "read option %u not supported\n", option );
2442 return E_NOTIMPL;
2444 if (size != sizeof(*ptr)) return E_INVALIDARG;
2445 return read_type_uint8( reader, mapping, desc, ptr );
2447 case WS_UINT16_TYPE:
2449 UINT16 *ptr = value;
2450 if (option != WS_READ_REQUIRED_VALUE)
2452 FIXME( "read option %u not supported\n", option );
2453 return E_NOTIMPL;
2455 if (size != sizeof(*ptr)) return E_INVALIDARG;
2456 return read_type_uint16( reader, mapping, desc, ptr );
2458 case WS_UINT32_TYPE:
2460 UINT32 *ptr = value;
2461 if (option != WS_READ_REQUIRED_VALUE)
2463 FIXME( "read option %u not supported\n", option );
2464 return E_NOTIMPL;
2466 if (size != sizeof(*ptr)) return E_INVALIDARG;
2467 return read_type_uint32( reader, mapping, desc, ptr );
2469 case WS_UINT64_TYPE:
2471 UINT64 *ptr = value;
2472 if (option != WS_READ_REQUIRED_VALUE)
2474 FIXME( "read option %u not supported\n", option );
2475 return E_NOTIMPL;
2477 if (size != sizeof(*ptr)) return E_INVALIDARG;
2478 return read_type_uint64( reader, mapping, desc, ptr );
2480 case WS_WSZ_TYPE:
2482 WCHAR **ptr = value;
2483 if (option != WS_READ_REQUIRED_POINTER)
2485 FIXME( "read option %u not supported\n", option );
2486 return E_NOTIMPL;
2488 if (size != sizeof(*ptr)) return E_INVALIDARG;
2489 return read_type_wsz( reader, mapping, desc, heap, ptr );
2491 default:
2492 FIXME( "type %u not supported\n", type );
2493 return E_NOTIMPL;
2497 /**************************************************************************
2498 * WsReadType [webservices.@]
2500 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
2501 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
2502 ULONG size, WS_ERROR *error )
2504 struct reader *reader = (struct reader *)handle;
2506 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
2507 size, error );
2508 if (error) FIXME( "ignoring error parameter\n" );
2510 if (!reader || !value) return E_INVALIDARG;
2512 return read_type( reader, mapping, type, desc, option, heap, value, size );
2515 /**************************************************************************
2516 * WsSetErrorProperty [webservices.@]
2518 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
2519 ULONG size )
2521 struct error *error = (struct error *)handle;
2523 TRACE( "%p %u %p %u\n", handle, id, value, size );
2525 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
2526 return set_error_prop( error, id, value, size );
2529 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
2531 static const char bom[] = {0xef,0xbb,0xbf};
2532 const unsigned char *p = data;
2534 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
2535 (size > 2 && !(*offset = 0));
2538 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
2540 static const char bom[] = {0xff,0xfe};
2541 const unsigned char *p = data;
2543 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
2544 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
2547 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
2549 WS_CHARSET ret = 0;
2551 /* FIXME: parse xml declaration */
2553 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
2554 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
2555 else
2557 FIXME( "charset not recognized\n" );
2558 return 0;
2561 TRACE( "detected charset %u\n", ret );
2562 return ret;
2565 static void set_input_buffer( struct reader *reader, const unsigned char *data, ULONG size )
2567 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
2568 reader->input_data = data;
2569 reader->input_size = size;
2571 reader->read_size = reader->input_size;
2572 reader->read_pos = 0;
2573 reader->read_bufptr = reader->input_data;
2576 /**************************************************************************
2577 * WsSetInput [webservices.@]
2579 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
2580 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
2581 ULONG count, WS_ERROR *error )
2583 struct reader *reader = (struct reader *)handle;
2584 struct node *node;
2585 HRESULT hr;
2586 ULONG i, offset = 0;
2588 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
2589 if (error) FIXME( "ignoring error parameter\n" );
2591 if (!reader) return E_INVALIDARG;
2593 for (i = 0; i < count; i++)
2595 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
2596 if (hr != S_OK) return hr;
2599 if ((hr = read_init_state( reader )) != S_OK) return hr;
2601 switch (encoding->encodingType)
2603 case WS_XML_READER_ENCODING_TYPE_TEXT:
2605 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
2606 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
2607 WS_CHARSET charset = text->charSet;
2609 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
2611 FIXME( "charset detection on input type %u not supported\n", input->inputType );
2612 return E_NOTIMPL;
2615 if (charset == WS_CHARSET_AUTO)
2616 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
2618 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
2619 if (hr != S_OK) return hr;
2620 break;
2622 default:
2623 FIXME( "encoding type %u not supported\n", encoding->encodingType );
2624 return E_NOTIMPL;
2626 switch (input->inputType)
2628 case WS_XML_READER_INPUT_TYPE_BUFFER:
2630 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
2631 set_input_buffer( reader, (const unsigned char *)buf->encodedData + offset, buf->encodedDataSize - offset );
2632 break;
2634 default:
2635 FIXME( "input type %u not supported\n", input->inputType );
2636 return E_NOTIMPL;
2639 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
2640 read_insert_bof( reader, node );
2641 return S_OK;
2644 /**************************************************************************
2645 * WsSetInputToBuffer [webservices.@]
2647 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
2648 const WS_XML_READER_PROPERTY *properties, ULONG count,
2649 WS_ERROR *error )
2651 struct reader *reader = (struct reader *)handle;
2652 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
2653 WS_CHARSET charset;
2654 struct node *node;
2655 HRESULT hr;
2656 ULONG i, offset = 0;
2658 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
2659 if (error) FIXME( "ignoring error parameter\n" );
2661 if (!reader || !xmlbuf) return E_INVALIDARG;
2663 for (i = 0; i < count; i++)
2665 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
2666 if (hr != S_OK) return hr;
2669 if ((hr = read_init_state( reader )) != S_OK) return hr;
2671 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
2672 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
2673 if (hr != S_OK) return hr;
2675 set_input_buffer( reader, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
2676 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
2677 read_insert_bof( reader, node );
2678 return S_OK;
2681 /**************************************************************************
2682 * WsXmlStringEquals [webservices.@]
2684 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
2686 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
2687 if (error) FIXME( "ignoring error parameter\n" );
2689 if (!str1 || !str2) return E_INVALIDARG;
2691 if (str1->length != str2->length) return S_FALSE;
2692 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
2693 return S_FALSE;