webservices: Use addition in read_skip.
[wine.git] / dlls / webservices / reader.c
blobf12c11885946aef8f0478780005104b16d94f7b0
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 static void *ws_realloc_zero( WS_HEAP *handle, void *ptr, SIZE_T size )
181 struct heap *heap = (struct heap *)handle;
182 return HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, size );
185 void ws_free( WS_HEAP *handle, void *ptr )
187 struct heap *heap = (struct heap *)handle;
188 HeapFree( heap->handle, 0, ptr );
191 /**************************************************************************
192 * WsAlloc [webservices.@]
194 HRESULT WINAPI WsAlloc( WS_HEAP *handle, SIZE_T size, void **ptr, WS_ERROR *error )
196 void *mem;
198 TRACE( "%p %u %p %p\n", handle, (ULONG)size, ptr, error );
199 if (error) FIXME( "ignoring error parameter\n" );
201 if (!handle || !ptr) return E_INVALIDARG;
203 if (!(mem = ws_alloc( handle, size ))) return E_OUTOFMEMORY;
204 *ptr = mem;
205 return S_OK;
208 static struct heap *alloc_heap(void)
210 static const ULONG count = sizeof(heap_props)/sizeof(heap_props[0]);
211 struct heap *ret;
212 ULONG i, size = sizeof(*ret) + count * sizeof(WS_HEAP_PROPERTY);
213 char *ptr;
215 for (i = 0; i < count; i++) size += heap_props[i].size;
216 if (!(ret = heap_alloc_zero( size ))) return NULL;
218 ptr = (char *)&ret->prop[count];
219 for (i = 0; i < count; i++)
221 ret->prop[i].value = ptr;
222 ret->prop[i].valueSize = heap_props[i].size;
223 ptr += ret->prop[i].valueSize;
225 ret->prop_count = count;
226 return ret;
229 static HRESULT set_heap_prop( struct heap *heap, WS_HEAP_PROPERTY_ID id, const void *value, ULONG size )
231 if (id >= heap->prop_count || size != heap_props[id].size || heap_props[id].readonly)
232 return E_INVALIDARG;
234 memcpy( heap->prop[id].value, value, size );
235 return S_OK;
238 static HRESULT get_heap_prop( struct heap *heap, WS_HEAP_PROPERTY_ID id, void *buf, ULONG size )
240 if (id >= heap->prop_count || size != heap_props[id].size)
241 return E_INVALIDARG;
243 memcpy( buf, heap->prop[id].value, heap->prop[id].valueSize );
244 return S_OK;
247 /**************************************************************************
248 * WsCreateHeap [webservices.@]
250 HRESULT WINAPI WsCreateHeap( SIZE_T max_size, SIZE_T trim_size, const WS_HEAP_PROPERTY *properties,
251 ULONG count, WS_HEAP **handle, WS_ERROR *error )
253 struct heap *heap;
255 TRACE( "%u %u %p %u %p %p\n", (ULONG)max_size, (ULONG)trim_size, properties, count, handle, error );
256 if (error) FIXME( "ignoring error parameter\n" );
258 if (!handle || count) return E_INVALIDARG;
259 if (!(heap = alloc_heap())) return E_OUTOFMEMORY;
261 set_heap_prop( heap, WS_HEAP_PROPERTY_MAX_SIZE, &max_size, sizeof(max_size) );
262 set_heap_prop( heap, WS_HEAP_PROPERTY_TRIM_SIZE, &trim_size, sizeof(trim_size) );
264 if (!(heap->handle = HeapCreate( 0, 0, max_size )))
266 heap_free( heap );
267 return E_OUTOFMEMORY;
270 *handle = (WS_HEAP *)heap;
271 return S_OK;
274 /**************************************************************************
275 * WsFreeHeap [webservices.@]
277 void WINAPI WsFreeHeap( WS_HEAP *handle )
279 struct heap *heap = (struct heap *)handle;
281 TRACE( "%p\n", handle );
283 if (!heap) return;
284 HeapDestroy( heap->handle );
285 heap_free( heap );
288 struct node *alloc_node( WS_XML_NODE_TYPE type )
290 struct node *ret;
292 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
293 ret->hdr.node.nodeType = type;
294 list_init( &ret->entry );
295 list_init( &ret->children );
296 return ret;
299 void free_attribute( WS_XML_ATTRIBUTE *attr )
301 if (!attr) return;
302 heap_free( attr->prefix );
303 heap_free( attr->localName );
304 heap_free( attr->ns );
305 heap_free( attr->value );
306 heap_free( attr );
309 void free_node( struct node *node )
311 if (!node) return;
312 switch (node_type( node ))
314 case WS_XML_NODE_TYPE_ELEMENT:
316 WS_XML_ELEMENT_NODE *elem = &node->hdr;
317 ULONG i;
319 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
320 heap_free( elem->attributes );
321 heap_free( elem->prefix );
322 heap_free( elem->localName );
323 heap_free( elem->ns );
324 break;
326 case WS_XML_NODE_TYPE_TEXT:
328 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
329 heap_free( text->text );
330 break;
332 case WS_XML_NODE_TYPE_COMMENT:
334 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
335 heap_free( comment->value.bytes );
336 break;
338 case WS_XML_NODE_TYPE_CDATA:
339 case WS_XML_NODE_TYPE_END_CDATA:
340 case WS_XML_NODE_TYPE_END_ELEMENT:
341 case WS_XML_NODE_TYPE_EOF:
342 case WS_XML_NODE_TYPE_BOF:
343 break;
345 default:
346 ERR( "unhandled type %u\n", node_type( node ) );
347 break;
349 heap_free( node );
352 void destroy_nodes( struct node *node )
354 struct list *ptr;
356 if (!node) return;
357 while ((ptr = list_head( &node->children )))
359 struct node *child = LIST_ENTRY( ptr, struct node, entry );
360 list_remove( &child->entry );
361 destroy_nodes( child );
363 free_node( node );
366 static const struct
368 ULONG size;
369 BOOL readonly;
371 reader_props[] =
373 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
374 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
375 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
376 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
377 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
378 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
379 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
380 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
381 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
382 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
383 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
384 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
385 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
386 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
387 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
390 enum reader_state
392 READER_STATE_INITIAL,
393 READER_STATE_BOF,
394 READER_STATE_STARTELEMENT,
395 READER_STATE_STARTATTRIBUTE,
396 READER_STATE_STARTCDATA,
397 READER_STATE_CDATA,
398 READER_STATE_TEXT,
399 READER_STATE_ENDELEMENT,
400 READER_STATE_ENDCDATA,
401 READER_STATE_COMMENT,
402 READER_STATE_EOF
405 struct prefix
407 WS_XML_STRING str;
408 WS_XML_STRING ns;
411 struct reader
413 ULONG read_size;
414 ULONG read_pos;
415 const unsigned char *read_bufptr;
416 enum reader_state state;
417 struct node *root;
418 struct node *current;
419 ULONG current_attr;
420 struct prefix *prefixes;
421 ULONG nb_prefixes;
422 ULONG nb_prefixes_allocated;
423 WS_XML_READER_INPUT_TYPE input_type;
424 const unsigned char *input_data;
425 ULONG input_size;
426 ULONG prop_count;
427 WS_XML_READER_PROPERTY prop[sizeof(reader_props)/sizeof(reader_props[0])];
430 static struct reader *alloc_reader(void)
432 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
433 struct reader *ret;
434 ULONG i, size = sizeof(*ret) + count * sizeof(WS_XML_READER_PROPERTY);
435 char *ptr;
437 for (i = 0; i < count; i++) size += reader_props[i].size;
438 if (!(ret = heap_alloc_zero( size ))) return NULL;
440 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
442 heap_free( ret );
443 return NULL;
445 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
447 ptr = (char *)&ret->prop[count];
448 for (i = 0; i < count; i++)
450 ret->prop[i].value = ptr;
451 ret->prop[i].valueSize = reader_props[i].size;
452 ptr += ret->prop[i].valueSize;
454 ret->prop_count = count;
455 return ret;
458 static void clear_prefixes( struct prefix *prefixes, ULONG count )
460 ULONG i;
461 for (i = 0; i < count; i++)
463 heap_free( prefixes[i].str.bytes );
464 prefixes[i].str.bytes = NULL;
465 prefixes[i].str.length = 0;
467 heap_free( prefixes[i].ns.bytes );
468 prefixes[i].ns.bytes = NULL;
469 prefixes[i].ns.length = 0;
473 static void free_reader( struct reader *reader )
475 if (!reader) return;
476 destroy_nodes( reader->root );
477 clear_prefixes( reader->prefixes, reader->nb_prefixes );
478 heap_free( reader->prefixes );
479 heap_free( reader );
482 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
484 if (str)
486 heap_free( prefix->str.bytes );
487 if (!(prefix->str.bytes = heap_alloc( str->length ))) return E_OUTOFMEMORY;
488 memcpy( prefix->str.bytes, str->bytes, str->length );
489 prefix->str.length = str->length;
492 heap_free( prefix->ns.bytes );
493 if (!(prefix->ns.bytes = heap_alloc( ns->length ))) return E_OUTOFMEMORY;
494 memcpy( prefix->ns.bytes, ns->bytes, ns->length );
495 prefix->ns.length = ns->length;
497 return S_OK;
500 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
502 ULONG i;
503 HRESULT hr;
505 for (i = 0; i < reader->nb_prefixes; i++)
507 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
508 return set_prefix( &reader->prefixes[i], NULL, ns );
510 if (i >= reader->nb_prefixes_allocated)
512 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
513 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
514 if (!tmp) return E_OUTOFMEMORY;
515 reader->prefixes = tmp;
516 reader->nb_prefixes_allocated *= 2;
519 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
520 reader->nb_prefixes++;
521 return S_OK;
524 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
526 ULONG i;
527 for (i = 0; i < reader->nb_prefixes; i++)
529 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
530 return &reader->prefixes[i].ns;
532 return NULL;
535 static HRESULT set_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID id, const void *value, ULONG size )
537 if (id >= reader->prop_count || size != reader_props[id].size || reader_props[id].readonly)
538 return E_INVALIDARG;
540 memcpy( reader->prop[id].value, value, size );
541 return S_OK;
544 static HRESULT get_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID id, void *buf, ULONG size )
546 if (id >= reader->prop_count || size != reader_props[id].size)
547 return E_INVALIDARG;
549 memcpy( buf, reader->prop[id].value, reader->prop[id].valueSize );
550 return S_OK;
553 static void read_insert_eof( struct reader *reader, struct node *eof )
555 if (!reader->root) reader->root = eof;
556 else
558 eof->parent = reader->root;
559 list_add_tail( &reader->root->children, &eof->entry );
561 reader->current = eof;
564 static void read_insert_bof( struct reader *reader, struct node *bof )
566 reader->root->parent = bof;
567 list_add_tail( &bof->children, &reader->root->entry );
568 reader->current = reader->root = bof;
571 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
573 node->parent = parent;
574 if (node->parent == reader->root)
576 struct list *eof = list_tail( &reader->root->children );
577 list_add_before( eof, &node->entry );
579 else list_add_tail( &parent->children, &node->entry );
580 reader->current = node;
583 static HRESULT read_init_state( struct reader *reader )
585 struct node *node;
587 destroy_nodes( reader->root );
588 reader->root = NULL;
589 clear_prefixes( reader->prefixes, reader->nb_prefixes );
590 reader->nb_prefixes = 1;
591 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
592 read_insert_eof( reader, node );
593 reader->state = READER_STATE_INITIAL;
594 return S_OK;
597 /**************************************************************************
598 * WsCreateReader [webservices.@]
600 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
601 WS_XML_READER **handle, WS_ERROR *error )
603 struct reader *reader;
604 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
605 WS_CHARSET charset = WS_CHARSET_UTF8;
606 BOOL read_decl = TRUE;
607 HRESULT hr;
609 TRACE( "%p %u %p %p\n", properties, count, handle, error );
610 if (error) FIXME( "ignoring error parameter\n" );
612 if (!handle) return E_INVALIDARG;
613 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
615 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
616 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
617 set_reader_prop( reader, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
618 set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
619 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
621 for (i = 0; i < count; i++)
623 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
624 if (hr != S_OK)
626 free_reader( reader );
627 return hr;
631 if ((hr = read_init_state( reader )) != S_OK)
633 free_reader( reader );
634 return hr;
637 *handle = (WS_XML_READER *)reader;
638 return S_OK;
641 /**************************************************************************
642 * WsFreeReader [webservices.@]
644 void WINAPI WsFreeReader( WS_XML_READER *handle )
646 struct reader *reader = (struct reader *)handle;
648 TRACE( "%p\n", handle );
649 free_reader( reader );
652 /**************************************************************************
653 * WsFillReader [webservices.@]
655 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
656 WS_ERROR *error )
658 struct reader *reader = (struct reader *)handle;
660 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
661 if (error) FIXME( "ignoring error parameter\n" );
663 if (!reader) return E_INVALIDARG;
665 /* FIXME: add support for stream input */
666 reader->read_size = min( min_size, reader->input_size );
667 reader->read_pos = 0;
669 return S_OK;
672 /**************************************************************************
673 * WsGetErrorProperty [webservices.@]
675 HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf,
676 ULONG size )
678 struct error *error = (struct error *)handle;
680 TRACE( "%p %u %p %u\n", handle, id, buf, size );
681 return get_error_prop( error, id, buf, size );
684 /**************************************************************************
685 * WsGetErrorString [webservices.@]
687 HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str )
689 FIXME( "%p %u %p: stub\n", handle, index, str );
690 return E_NOTIMPL;
693 /**************************************************************************
694 * WsGetHeapProperty [webservices.@]
696 HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
697 ULONG size, WS_ERROR *error )
699 struct heap *heap = (struct heap *)handle;
701 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
702 if (error) FIXME( "ignoring error parameter\n" );
704 return get_heap_prop( heap, id, buf, size );
707 /**************************************************************************
708 * WsGetNamespaceFromPrefix [webservices.@]
710 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
711 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
713 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
714 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
715 static const WS_XML_STRING empty_ns = {0, NULL};
716 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
717 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
718 struct reader *reader = (struct reader *)handle;
719 BOOL found = FALSE;
721 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
722 if (error) FIXME( "ignoring error parameter\n" );
724 if (!reader || !prefix || !ns) return E_INVALIDARG;
725 if (reader->state != READER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
727 if (!prefix->length)
729 *ns = &empty_ns;
730 found = TRUE;
732 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
734 *ns = &xml_ns;
735 found = TRUE;
737 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
739 *ns = &xmlns_ns;
740 found = TRUE;
742 else
744 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
745 ULONG i;
747 for (i = 0; i < elem->attributeCount; i++)
749 if (!elem->attributes[i]->isXmlNs) continue;
750 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
752 *ns = elem->attributes[i]->ns;
753 found = TRUE;
754 break;
759 if (!found)
761 if (required) return WS_E_INVALID_FORMAT;
762 *ns = NULL;
763 return S_FALSE;
765 return S_OK;
768 /**************************************************************************
769 * WsGetReaderNode [webservices.@]
771 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
772 WS_ERROR *error )
774 struct reader *reader = (struct reader *)handle;
776 TRACE( "%p %p %p\n", handle, node, error );
777 if (error) FIXME( "ignoring error parameter\n" );
779 if (!reader || !node) return E_INVALIDARG;
781 *node = &reader->current->hdr.node;
782 return S_OK;
785 /**************************************************************************
786 * WsGetReaderProperty [webservices.@]
788 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
789 void *buf, ULONG size, WS_ERROR *error )
791 struct reader *reader = (struct reader *)handle;
793 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
794 if (error) FIXME( "ignoring error parameter\n" );
796 if (!reader->input_type) return WS_E_INVALID_OPERATION;
798 if (id == WS_XML_READER_PROPERTY_CHARSET)
800 WS_CHARSET charset;
801 HRESULT hr;
803 if ((hr = get_reader_prop( reader, id, &charset, size )) != S_OK) return hr;
804 if (!charset) return WS_E_INVALID_FORMAT;
805 *(WS_CHARSET *)buf = charset;
806 return S_OK;
808 return get_reader_prop( reader, id, buf, size );
811 /**************************************************************************
812 * WsGetXmlAttribute [webservices.@]
814 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
815 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
817 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
818 return E_NOTIMPL;
821 WS_XML_STRING *alloc_xml_string( const unsigned char *data, ULONG len )
823 WS_XML_STRING *ret;
825 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
826 ret->length = len;
827 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
828 ret->dictionary = NULL;
829 ret->id = 0;
830 if (data) memcpy( ret->bytes, data, len );
831 return ret;
834 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *data, ULONG len )
836 WS_XML_UTF8_TEXT *ret;
838 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
839 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
840 ret->value.length = len;
841 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
842 ret->value.dictionary = NULL;
843 ret->value.id = 0;
844 if (data) memcpy( ret->value.bytes, data, len );
845 return ret;
848 static inline BOOL read_end_of_data( struct reader *reader )
850 return reader->read_pos >= reader->read_size;
853 static inline const unsigned char *read_current_ptr( struct reader *reader )
855 return &reader->read_bufptr[reader->read_pos];
858 /* UTF-8 support based on libs/wine/utf8.c */
860 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
861 static const char utf8_length[128] =
863 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
864 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
865 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
866 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
867 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
868 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
869 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
870 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
873 /* first byte mask depending on UTF-8 sequence length */
874 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
876 /* minimum Unicode value depending on UTF-8 sequence length */
877 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
879 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
881 unsigned int len, res;
882 unsigned char ch = reader->read_bufptr[reader->read_pos];
883 const unsigned char *end;
885 if (reader->read_pos >= reader->read_size) return 0;
887 if (ch < 0x80)
889 *skip = 1;
890 return ch;
892 len = utf8_length[ch - 0x80];
893 if (reader->read_pos + len >= reader->read_size) return 0;
894 end = reader->read_bufptr + reader->read_pos + len;
895 res = ch & utf8_mask[len];
897 switch (len)
899 case 3:
900 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
901 res = (res << 6) | ch;
902 case 2:
903 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
904 res = (res << 6) | ch;
905 case 1:
906 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
907 res = (res << 6) | ch;
908 if (res < utf8_minval[len]) break;
909 *skip = len + 1;
910 return res;
913 return 0;
916 static inline void read_skip( struct reader *reader, unsigned int count )
918 if (reader->read_pos + count > reader->read_size) return;
919 reader->read_pos += count;
922 static inline BOOL read_isnamechar( unsigned int ch )
924 /* FIXME: incomplete */
925 return (ch >= 'A' && ch <= 'Z') ||
926 (ch >= 'a' && ch <= 'z') ||
927 (ch >= '0' && ch <= '9') ||
928 ch == '_' || ch == '-' || ch == '.' || ch == ':';
931 static inline BOOL read_isspace( unsigned int ch )
933 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
936 static inline void read_skip_whitespace( struct reader *reader )
938 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
939 reader->read_pos++;
942 static inline int read_cmp( struct reader *reader, const char *str, int len )
944 const unsigned char *ptr = read_current_ptr( reader );
946 if (len < 0) len = strlen( str );
947 if (reader->read_pos + len > reader->read_size) return -1;
948 while (len--)
950 if (*str != *ptr) return *ptr - *str;
951 str++; ptr++;
953 return 0;
956 static HRESULT read_xmldecl( struct reader *reader )
958 if (!reader->read_size) return WS_E_INVALID_FORMAT;
960 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
962 reader->state = READER_STATE_BOF;
963 return S_OK;
965 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
966 read_skip( reader, 6 );
968 /* FIXME: parse attributes */
969 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
970 reader->read_pos++;
972 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
973 read_skip( reader, 2 );
975 reader->state = READER_STATE_BOF;
976 return S_OK;
979 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
981 if (elem->attributeCount)
983 WS_XML_ATTRIBUTE **tmp;
984 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
985 return E_OUTOFMEMORY;
986 elem->attributes = tmp;
988 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
989 elem->attributes[elem->attributeCount++] = attr;
990 return S_OK;
993 static HRESULT parse_name( const unsigned char *str, unsigned int len,
994 WS_XML_STRING **prefix, WS_XML_STRING **localname )
996 const unsigned char *name_ptr = str, *prefix_ptr = NULL;
997 unsigned int i, name_len = len, prefix_len = 0;
999 for (i = 0; i < len; i++)
1001 if (str[i] == ':')
1003 prefix_ptr = str;
1004 prefix_len = i;
1005 name_ptr = &str[i + 1];
1006 name_len -= i + 1;
1007 break;
1010 if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
1011 if (!(*localname = alloc_xml_string( name_ptr, name_len )))
1013 heap_free( *prefix );
1014 return E_OUTOFMEMORY;
1016 return S_OK;
1019 static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1021 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1022 WS_XML_ATTRIBUTE *attr;
1023 WS_XML_UTF8_TEXT *text;
1024 unsigned int len = 0, ch, skip, quote;
1025 const unsigned char *start;
1026 WS_XML_STRING *prefix, *localname;
1027 HRESULT hr = WS_E_INVALID_FORMAT;
1029 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1031 start = read_current_ptr( reader );
1032 for (;;)
1034 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1035 if (!read_isnamechar( ch )) break;
1036 read_skip( reader, skip );
1037 len += skip;
1039 if (!len) goto error;
1041 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) goto error;
1042 hr = E_OUTOFMEMORY;
1043 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1045 heap_free( prefix );
1046 attr->isXmlNs = 1;
1047 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1049 heap_free( localname );
1050 goto error;
1052 attr->localName = localname;
1054 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1056 attr->isXmlNs = 1;
1057 attr->prefix = prefix;
1058 attr->localName = localname;
1060 else
1062 attr->prefix = prefix;
1063 attr->localName = localname;
1066 hr = WS_E_INVALID_FORMAT;
1067 read_skip_whitespace( reader );
1068 if (read_cmp( reader, "=", 1 )) goto error;
1069 read_skip( reader, 1 );
1071 read_skip_whitespace( reader );
1072 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) goto error;
1073 quote = read_utf8_char( reader, &skip );
1074 read_skip( reader, 1 );
1076 len = 0;
1077 start = read_current_ptr( reader );
1078 for (;;)
1080 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1081 if (ch == quote) break;
1082 read_skip( reader, skip );
1083 len += skip;
1085 read_skip( reader, 1 );
1087 hr = E_OUTOFMEMORY;
1088 if (attr->isXmlNs)
1090 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1091 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1092 if (!(text = alloc_utf8_text( NULL, 0 ))) goto error;
1094 else if (!(text = alloc_utf8_text( start, len ))) goto error;
1096 attr->value = &text->text;
1097 attr->singleQuote = (quote == '\'');
1099 *ret = attr;
1100 return S_OK;
1102 error:
1103 free_attribute( attr );
1104 return hr;
1107 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
1109 ULONG i;
1110 if (len1 != len2) return 1;
1111 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
1112 return 0;
1115 static struct node *read_find_parent( struct reader *reader, const WS_XML_STRING *prefix,
1116 const WS_XML_STRING *localname )
1118 struct node *parent;
1119 const WS_XML_STRING *str;
1121 for (parent = reader->current; parent; parent = parent->parent)
1123 if (node_type( parent ) == WS_XML_NODE_TYPE_BOF)
1125 if (!localname) return parent;
1126 return NULL;
1128 else if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
1130 if (!localname) return parent;
1132 str = parent->hdr.prefix;
1133 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
1134 str = parent->hdr.localName;
1135 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
1136 return parent;
1140 return NULL;
1143 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1145 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1146 const WS_XML_STRING *ns;
1147 ULONG i;
1149 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1150 if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1151 if (!elem->ns->length) elem->ns->bytes = (BYTE *)(elem->ns + 1); /* quirk */
1153 for (i = 0; i < elem->attributeCount; i++)
1155 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1156 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1157 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1158 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1160 return S_OK;
1163 static HRESULT read_element( struct reader *reader )
1165 unsigned int len = 0, ch, skip;
1166 const unsigned char *start;
1167 struct node *node = NULL, *parent;
1168 WS_XML_ELEMENT_NODE *elem;
1169 WS_XML_ATTRIBUTE *attr = NULL;
1170 HRESULT hr = WS_E_INVALID_FORMAT;
1172 if (read_end_of_data( reader ))
1174 struct list *eof = list_tail( &reader->root->children );
1175 reader->current = LIST_ENTRY( eof, struct node, entry );
1176 reader->state = READER_STATE_EOF;
1177 return S_OK;
1180 if (read_cmp( reader, "<", 1 )) goto error;
1181 read_skip( reader, 1 );
1183 start = read_current_ptr( reader );
1184 for (;;)
1186 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1187 if (!read_isnamechar( ch )) break;
1188 read_skip( reader, skip );
1189 len += skip;
1191 if (!len) goto error;
1193 if (!(parent = read_find_parent( reader, NULL, NULL ))) goto error;
1195 hr = E_OUTOFMEMORY;
1196 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error;
1197 elem = (WS_XML_ELEMENT_NODE *)node;
1198 if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1200 reader->current_attr = 0;
1201 for (;;)
1203 read_skip_whitespace( reader );
1204 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1205 if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
1206 if ((hr = append_attribute( elem, attr )) != S_OK)
1208 free_attribute( attr );
1209 goto error;
1211 reader->current_attr++;
1213 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1215 read_insert_node( reader, parent, node );
1216 reader->state = READER_STATE_STARTELEMENT;
1217 return S_OK;
1219 error:
1220 free_node( node );
1221 return hr;
1224 static HRESULT read_text( struct reader *reader )
1226 unsigned int len = 0, ch, skip;
1227 const unsigned char *start;
1228 struct node *node;
1229 WS_XML_TEXT_NODE *text;
1230 WS_XML_UTF8_TEXT *utf8;
1232 start = read_current_ptr( reader );
1233 for (;;)
1235 if (read_end_of_data( reader )) break;
1236 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1237 if (ch == '<') break;
1238 read_skip( reader, skip );
1239 len += skip;
1242 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1243 text = (WS_XML_TEXT_NODE *)node;
1244 if (!(utf8 = alloc_utf8_text( start, len )))
1246 heap_free( node );
1247 return E_OUTOFMEMORY;
1249 text->text = &utf8->text;
1251 read_insert_node( reader, reader->current, node );
1252 reader->state = READER_STATE_TEXT;
1253 return S_OK;
1256 static HRESULT read_node( struct reader * );
1258 static HRESULT read_startelement( struct reader *reader )
1260 struct node *node;
1262 read_skip_whitespace( reader );
1263 if (!read_cmp( reader, "/>", 2 ))
1265 read_skip( reader, 2 );
1266 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1267 read_insert_node( reader, reader->current, node );
1268 reader->state = READER_STATE_ENDELEMENT;
1269 return S_OK;
1271 else if (!read_cmp( reader, ">", 1 ))
1273 read_skip( reader, 1 );
1274 return read_node( reader );
1276 return WS_E_INVALID_FORMAT;
1279 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
1281 HRESULT hr;
1283 switch (reader->state)
1285 case READER_STATE_INITIAL:
1286 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
1287 break;
1289 case READER_STATE_STARTELEMENT:
1290 if (found) *found = TRUE;
1291 return S_OK;
1293 default:
1294 break;
1297 read_skip_whitespace( reader );
1298 if ((hr = read_element( reader )) == S_OK && found)
1300 if (reader->state == READER_STATE_STARTELEMENT)
1301 *found = TRUE;
1302 else
1303 *found = FALSE;
1306 return hr;
1309 static HRESULT read_endelement( struct reader *reader )
1311 struct node *node, *parent;
1312 unsigned int len = 0, ch, skip;
1313 const unsigned char *start;
1314 WS_XML_STRING *prefix, *localname;
1315 HRESULT hr;
1317 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
1319 if (read_end_of_data( reader ))
1321 struct list *eof = list_tail( &reader->root->children );
1322 reader->current = LIST_ENTRY( eof, struct node, entry );
1323 reader->state = READER_STATE_EOF;
1324 return S_OK;
1327 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
1328 read_skip( reader, 2 );
1330 start = read_current_ptr( reader );
1331 for (;;)
1333 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1334 if (ch == '>')
1336 read_skip( reader, 1 );
1337 break;
1339 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
1340 read_skip( reader, skip );
1341 len += skip;
1344 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
1345 parent = read_find_parent( reader, prefix, localname );
1346 heap_free( prefix );
1347 heap_free( localname );
1348 if (!parent) return WS_E_INVALID_FORMAT;
1350 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1351 read_insert_node( reader, parent, node );
1352 reader->state = READER_STATE_ENDELEMENT;
1353 return S_OK;
1356 static HRESULT read_comment( struct reader *reader )
1358 unsigned int len = 0, ch, skip;
1359 const unsigned char *start;
1360 struct node *node;
1361 WS_XML_COMMENT_NODE *comment;
1363 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
1364 read_skip( reader, 4 );
1366 start = read_current_ptr( reader );
1367 for (;;)
1369 if (!read_cmp( reader, "-->", 3 ))
1371 read_skip( reader, 3 );
1372 break;
1374 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1375 read_skip( reader, skip );
1376 len += skip;
1379 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
1380 comment = (WS_XML_COMMENT_NODE *)node;
1381 if (!(comment->value.bytes = heap_alloc( len )))
1383 heap_free( node );
1384 return E_OUTOFMEMORY;
1386 memcpy( comment->value.bytes, start, len );
1387 comment->value.length = len;
1389 read_insert_node( reader, reader->current, node );
1390 reader->state = READER_STATE_COMMENT;
1391 return S_OK;
1394 static HRESULT read_startcdata( struct reader *reader )
1396 struct node *node;
1398 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
1399 read_skip( reader, 9 );
1401 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
1402 read_insert_node( reader, reader->current, node );
1403 reader->state = READER_STATE_STARTCDATA;
1404 return S_OK;
1407 static HRESULT read_cdata( struct reader *reader )
1409 unsigned int len = 0, ch, skip;
1410 const unsigned char *start;
1411 struct node *node;
1412 WS_XML_TEXT_NODE *text;
1413 WS_XML_UTF8_TEXT *utf8;
1415 start = read_current_ptr( reader );
1416 for (;;)
1418 if (!read_cmp( reader, "]]>", 3 )) break;
1419 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1420 read_skip( reader, skip );
1421 len += skip;
1424 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1425 text = (WS_XML_TEXT_NODE *)node;
1426 if (!(utf8 = alloc_utf8_text( start, len )))
1428 heap_free( node );
1429 return E_OUTOFMEMORY;
1431 text->text = &utf8->text;
1433 read_insert_node( reader, reader->current, node );
1434 reader->state = READER_STATE_CDATA;
1435 return S_OK;
1438 static HRESULT read_endcdata( struct reader *reader )
1440 struct node *node;
1442 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
1443 read_skip( reader, 3 );
1445 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_CDATA ))) return E_OUTOFMEMORY;
1446 read_insert_node( reader, reader->current->parent, node );
1447 reader->state = READER_STATE_ENDCDATA;
1448 return S_OK;
1451 static HRESULT read_node( struct reader *reader )
1453 HRESULT hr;
1455 for (;;)
1457 if (read_end_of_data( reader ))
1459 struct list *eof = list_tail( &reader->root->children );
1460 reader->current = LIST_ENTRY( eof, struct node, entry );
1461 reader->state = READER_STATE_EOF;
1462 return S_OK;
1464 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
1465 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
1466 else if (!read_cmp( reader, "<?", 2 ))
1468 hr = read_xmldecl( reader );
1469 if (FAILED( hr )) return hr;
1471 else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
1472 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
1473 else if (!read_cmp( reader, "<!--", 4 )) return read_comment( reader );
1474 else if (!read_cmp( reader, "<", 1 )) return read_element( reader );
1475 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement( reader );
1476 else return read_text( reader );
1480 /**************************************************************************
1481 * WsReadEndElement [webservices.@]
1483 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
1485 struct reader *reader = (struct reader *)handle;
1487 TRACE( "%p %p\n", handle, error );
1488 if (error) FIXME( "ignoring error parameter\n" );
1490 if (!reader) return E_INVALIDARG;
1491 return read_endelement( reader );
1494 /**************************************************************************
1495 * WsReadNode [webservices.@]
1497 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
1499 struct reader *reader = (struct reader *)handle;
1501 TRACE( "%p %p\n", handle, error );
1502 if (error) FIXME( "ignoring error parameter\n" );
1504 if (!reader) return E_INVALIDARG;
1505 return read_node( reader );
1508 /**************************************************************************
1509 * WsReadStartElement [webservices.@]
1511 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
1513 struct reader *reader = (struct reader *)handle;
1515 TRACE( "%p %p\n", handle, error );
1516 if (error) FIXME( "ignoring error parameter\n" );
1518 if (!reader) return E_INVALIDARG;
1519 return read_startelement( reader );
1522 /**************************************************************************
1523 * WsReadToStartElement [webservices.@]
1525 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
1526 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
1528 struct reader *reader = (struct reader *)handle;
1530 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
1531 if (error) FIXME( "ignoring error parameter\n" );
1533 if (!reader) return E_INVALIDARG;
1534 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
1536 return read_to_startelement( reader, found );
1539 static BOOL move_to_root_element( struct reader *reader )
1541 struct list *ptr;
1542 struct node *node;
1544 if (!(ptr = list_head( &reader->root->children ))) return FALSE;
1545 node = LIST_ENTRY( ptr, struct node, entry );
1546 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1548 reader->current = node;
1549 return TRUE;
1551 while ((ptr = list_next( &reader->root->children, &node->entry )))
1553 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1554 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1556 reader->current = next;
1557 return TRUE;
1559 node = next;
1561 return FALSE;
1564 static BOOL move_to_next_element( struct reader *reader )
1566 struct list *ptr;
1567 struct node *node = reader->current;
1569 while ((ptr = list_next( &node->parent->children, &node->entry )))
1571 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1572 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1574 reader->current = next;
1575 return TRUE;
1577 node = next;
1579 return FALSE;
1582 static BOOL move_to_prev_element( struct reader *reader )
1584 struct list *ptr;
1585 struct node *node = reader->current;
1587 while ((ptr = list_prev( &node->parent->children, &node->entry )))
1589 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
1590 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
1592 reader->current = prev;
1593 return TRUE;
1595 node = prev;
1597 return FALSE;
1600 static BOOL move_to_child_element( struct reader *reader )
1602 struct list *ptr;
1603 struct node *node;
1605 if (!(ptr = list_head( &reader->current->children ))) return FALSE;
1606 node = LIST_ENTRY( ptr, struct node, entry );
1607 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1609 reader->current = node;
1610 return TRUE;
1612 while ((ptr = list_next( &reader->current->children, &node->entry )))
1614 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1615 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1617 reader->current = next;
1618 return TRUE;
1620 node = next;
1622 return FALSE;
1625 static BOOL move_to_end_element( struct reader *reader )
1627 struct list *ptr;
1628 struct node *node = reader->current;
1630 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
1632 if ((ptr = list_tail( &node->children )))
1634 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
1635 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
1637 reader->current = tail;
1638 return TRUE;
1641 return FALSE;
1644 static BOOL move_to_parent_element( struct reader *reader )
1646 struct node *parent = reader->current->parent;
1648 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
1649 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
1651 reader->current = parent;
1652 return TRUE;
1654 return FALSE;
1657 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
1659 struct list *ptr;
1660 BOOL success = FALSE;
1661 HRESULT hr = S_OK;
1663 if (!read_end_of_data( reader ))
1665 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
1666 if (hr != S_OK) return hr;
1668 switch (move)
1670 case WS_MOVE_TO_ROOT_ELEMENT:
1671 success = move_to_root_element( reader );
1672 break;
1674 case WS_MOVE_TO_NEXT_ELEMENT:
1675 success = move_to_next_element( reader );
1676 break;
1678 case WS_MOVE_TO_PREVIOUS_ELEMENT:
1679 success = move_to_prev_element( reader );
1680 break;
1682 case WS_MOVE_TO_CHILD_ELEMENT:
1683 success = move_to_child_element( reader );
1684 break;
1686 case WS_MOVE_TO_END_ELEMENT:
1687 success = move_to_end_element( reader );
1688 break;
1690 case WS_MOVE_TO_PARENT_ELEMENT:
1691 success = move_to_parent_element( reader );
1692 break;
1694 case WS_MOVE_TO_FIRST_NODE:
1695 if ((ptr = list_head( &reader->current->parent->children )))
1697 reader->current = LIST_ENTRY( ptr, struct node, entry );
1698 success = TRUE;
1700 break;
1702 case WS_MOVE_TO_NEXT_NODE:
1703 if ((ptr = list_next( &reader->current->parent->children, &reader->current->entry )))
1705 reader->current = LIST_ENTRY( ptr, struct node, entry );
1706 success = TRUE;
1708 break;
1710 case WS_MOVE_TO_PREVIOUS_NODE:
1711 if ((ptr = list_prev( &reader->current->parent->children, &reader->current->entry )))
1713 reader->current = LIST_ENTRY( ptr, struct node, entry );
1714 success = TRUE;
1716 break;
1718 case WS_MOVE_TO_CHILD_NODE:
1719 if ((ptr = list_head( &reader->current->children )))
1721 reader->current = LIST_ENTRY( ptr, struct node, entry );
1722 success = TRUE;
1724 break;
1726 case WS_MOVE_TO_BOF:
1727 reader->current = reader->root;
1728 success = TRUE;
1729 break;
1731 case WS_MOVE_TO_EOF:
1732 if ((ptr = list_tail( &reader->root->children )))
1734 reader->current = LIST_ENTRY( ptr, struct node, entry );
1735 success = TRUE;
1737 break;
1739 default:
1740 FIXME( "unhandled move %u\n", move );
1741 return E_NOTIMPL;
1744 if (found)
1746 *found = success;
1747 return S_OK;
1749 return success ? S_OK : WS_E_INVALID_FORMAT;
1752 /**************************************************************************
1753 * WsMoveReader [webservices.@]
1755 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
1757 struct reader *reader = (struct reader *)handle;
1759 TRACE( "%p %u %p %p\n", handle, move, found, error );
1760 if (error) FIXME( "ignoring error parameter\n" );
1762 if (!reader) return E_INVALIDARG;
1763 if (!reader->input_type) return WS_E_INVALID_OPERATION;
1765 return read_move_to( reader, move, found );
1768 /**************************************************************************
1769 * WsReadStartAttribute [webservices.@]
1771 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
1773 struct reader *reader = (struct reader *)handle;
1774 WS_XML_ELEMENT_NODE *elem;
1776 TRACE( "%p %u %p\n", handle, index, error );
1777 if (error) FIXME( "ignoring error parameter\n" );
1779 if (!reader) return E_INVALIDARG;
1781 elem = &reader->current->hdr;
1782 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
1783 return WS_E_INVALID_FORMAT;
1785 reader->current_attr = index;
1786 reader->state = READER_STATE_STARTATTRIBUTE;
1787 return S_OK;
1790 /**************************************************************************
1791 * WsReadEndAttribute [webservices.@]
1793 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
1795 struct reader *reader = (struct reader *)handle;
1797 TRACE( "%p %p\n", handle, error );
1798 if (error) FIXME( "ignoring error parameter\n" );
1800 if (!reader) return E_INVALIDARG;
1802 if (reader->state != READER_STATE_STARTATTRIBUTE)
1803 return WS_E_INVALID_FORMAT;
1805 reader->state = READER_STATE_STARTELEMENT;
1806 return S_OK;
1809 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
1811 WCHAR *ret;
1813 switch (text->textType)
1815 case WS_XML_TEXT_TYPE_UTF8:
1817 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
1818 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
1819 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
1820 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
1821 ret[len] = 0;
1822 break;
1824 default:
1825 FIXME( "unhandled type %u\n", text->textType );
1826 return NULL;
1829 return ret;
1832 #define MAX_INT8 0x7f
1833 #define MIN_INT8 (-MAX_INT8 - 1)
1834 #define MAX_INT16 0x7fff
1835 #define MIN_INT16 (-MAX_INT16 - 1)
1836 #define MAX_INT32 0x7fffffff
1837 #define MIN_INT32 (-MAX_INT32 - 1)
1838 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1839 #define MIN_INT64 (-MAX_INT64 - 1)
1840 #define MAX_UINT8 0xff
1841 #define MAX_UINT16 0xffff
1842 #define MAX_UINT32 0xffffffff
1843 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1845 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
1847 BOOL negative = FALSE;
1848 const unsigned char *ptr = str;
1850 *ret = 0;
1851 while (len && read_isspace( *ptr )) { ptr++; len--; }
1852 while (len && read_isspace( ptr[len - 1] )) { len--; }
1853 if (!len) return WS_E_INVALID_FORMAT;
1855 if (*ptr == '-')
1857 negative = TRUE;
1858 ptr++;
1859 len--;
1861 if (!len) return WS_E_INVALID_FORMAT;
1863 while (len--)
1865 int val;
1867 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1868 val = *ptr - '0';
1869 if (negative) val = -val;
1871 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
1872 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
1874 return WS_E_NUMERIC_OVERFLOW;
1876 *ret = *ret * 10 + val;
1877 ptr++;
1880 return S_OK;
1883 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
1885 const unsigned char *ptr = str;
1887 *ret = 0;
1888 while (len && read_isspace( *ptr )) { ptr++; len--; }
1889 while (len && read_isspace( ptr[len - 1] )) { len--; }
1890 if (!len) return WS_E_INVALID_FORMAT;
1892 while (len--)
1894 unsigned int val;
1896 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1897 val = *ptr - '0';
1899 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
1900 *ret = *ret * 10 + val;
1901 ptr++;
1904 return S_OK;
1907 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
1909 WS_XML_TEXT_NODE *text;
1911 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
1912 return WS_E_INVALID_FORMAT;
1914 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
1915 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
1917 FIXME( "text type %u not supported\n", text->text->textType );
1918 return E_NOTIMPL;
1920 *ret = (WS_XML_UTF8_TEXT *)text->text;
1921 return S_OK;
1924 static HRESULT read_get_attribute_text( struct reader *reader, ULONG index, WS_XML_UTF8_TEXT **ret )
1926 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1927 WS_XML_ATTRIBUTE *attr;
1929 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
1930 return WS_E_INVALID_FORMAT;
1932 attr = elem->attributes[index];
1933 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
1935 FIXME( "text type %u not supported\n", attr->value->textType );
1936 return E_NOTIMPL;
1938 *ret = (WS_XML_UTF8_TEXT *)attr->value;
1939 return S_OK;
1942 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
1943 const WS_XML_STRING *ns, ULONG *index )
1945 ULONG i;
1946 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1948 if (!localname)
1950 *index = reader->current_attr;
1951 return TRUE;
1953 for (i = 0; i < elem->attributeCount; i++)
1955 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
1956 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
1958 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
1959 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
1961 *index = i;
1962 return TRUE;
1965 return FALSE;
1968 /**************************************************************************
1969 * WsFindAttribute [webservices.@]
1971 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
1972 const WS_XML_STRING *ns, BOOL required, ULONG *index,
1973 WS_ERROR *error )
1975 struct reader *reader = (struct reader *)handle;
1977 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
1978 required, index, error );
1979 if (error) FIXME( "ignoring error parameter\n" );
1981 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
1983 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
1984 return WS_E_INVALID_OPERATION;
1986 if (!find_attribute( reader, localname, ns, index ))
1988 if (required) return WS_E_INVALID_FORMAT;
1989 *index = ~0u;
1990 return S_FALSE;
1992 return S_OK;
1995 static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
1996 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
1997 WS_XML_UTF8_TEXT **ret, BOOL *found )
1999 switch (mapping)
2001 case WS_ATTRIBUTE_TYPE_MAPPING:
2003 ULONG index;
2004 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
2005 return read_get_attribute_text( reader, index, ret );
2007 case WS_ELEMENT_TYPE_MAPPING:
2008 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2010 HRESULT hr;
2011 *found = TRUE;
2012 if (localname)
2014 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2016 if (WsXmlStringEquals( localname, elem->localName, NULL ) != S_OK ||
2017 WsXmlStringEquals( ns, elem->ns, NULL ) != S_OK)
2019 *found = FALSE;
2020 return S_OK;
2022 if ((hr = read_startelement( reader )) != S_OK) return hr;
2024 return read_get_node_text( reader, ret );
2026 default:
2027 FIXME( "mapping %u not supported\n", mapping );
2028 return E_NOTIMPL;
2032 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
2033 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2034 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
2035 WS_HEAP *heap, void *ret, ULONG size )
2037 WS_XML_UTF8_TEXT *utf8;
2038 HRESULT hr;
2039 BOOL found, val = FALSE;
2041 if (desc)
2043 FIXME( "description not supported\n" );
2044 return E_NOTIMPL;
2046 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2047 if (found)
2049 ULONG len = utf8->value.length;
2050 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
2051 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
2052 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
2053 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
2054 else return WS_E_INVALID_FORMAT;
2057 switch (option)
2059 case WS_READ_REQUIRED_VALUE:
2060 if (!found) return WS_E_INVALID_FORMAT;
2061 if (size != sizeof(BOOL)) return E_INVALIDARG;
2062 *(BOOL *)ret = val;
2063 break;
2065 case WS_READ_REQUIRED_POINTER:
2066 if (!found) return WS_E_INVALID_FORMAT;
2067 /* fall through */
2069 case WS_READ_OPTIONAL_POINTER:
2071 BOOL *heap_val = NULL;
2072 if (size != sizeof(heap_val)) return E_INVALIDARG;
2073 if (found)
2075 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2076 *heap_val = val;
2078 *(BOOL **)ret = heap_val;
2079 break;
2081 default:
2082 FIXME( "read option %u not supported\n", option );
2083 return E_NOTIMPL;
2086 return S_OK;
2089 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
2090 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2091 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
2092 WS_HEAP *heap, void *ret, ULONG size )
2094 WS_XML_UTF8_TEXT *utf8;
2095 HRESULT hr;
2096 INT64 val;
2097 BOOL found;
2099 if (desc)
2101 FIXME( "description not supported\n" );
2102 return E_NOTIMPL;
2104 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2105 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
2106 return hr;
2108 switch (option)
2110 case WS_READ_REQUIRED_VALUE:
2111 if (!found) return WS_E_INVALID_FORMAT;
2112 if (size != sizeof(INT8)) return E_INVALIDARG;
2113 *(INT8 *)ret = val;
2114 break;
2116 case WS_READ_REQUIRED_POINTER:
2117 if (!found) return WS_E_INVALID_FORMAT;
2118 /* fall through */
2120 case WS_READ_OPTIONAL_POINTER:
2122 INT8 *heap_val = NULL;
2123 if (size != sizeof(heap_val)) return E_INVALIDARG;
2124 if (found)
2126 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2127 *heap_val = val;
2129 *(INT8 **)ret = heap_val;
2130 break;
2132 default:
2133 FIXME( "read option %u not supported\n", option );
2134 return E_NOTIMPL;
2137 return S_OK;
2140 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
2141 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2142 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
2143 WS_HEAP *heap, void *ret, ULONG size )
2145 WS_XML_UTF8_TEXT *utf8;
2146 HRESULT hr;
2147 INT64 val;
2148 BOOL found;
2150 if (desc)
2152 FIXME( "description not supported\n" );
2153 return E_NOTIMPL;
2155 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2156 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
2157 return hr;
2159 switch (option)
2161 case WS_READ_REQUIRED_VALUE:
2162 if (!found) return WS_E_INVALID_FORMAT;
2163 if (size != sizeof(INT16)) return E_INVALIDARG;
2164 *(INT16 *)ret = val;
2165 break;
2167 case WS_READ_REQUIRED_POINTER:
2168 if (!found) return WS_E_INVALID_FORMAT;
2169 /* fall through */
2171 case WS_READ_OPTIONAL_POINTER:
2173 INT16 *heap_val = NULL;
2174 if (size != sizeof(heap_val)) return E_INVALIDARG;
2175 if (found)
2177 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2178 *heap_val = val;
2180 *(INT16 **)ret = heap_val;
2181 break;
2183 default:
2184 FIXME( "read option %u not supported\n", option );
2185 return E_NOTIMPL;
2188 return S_OK;
2191 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
2192 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2193 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
2194 WS_HEAP *heap, void *ret, ULONG size )
2196 WS_XML_UTF8_TEXT *utf8;
2197 HRESULT hr;
2198 INT64 val;
2199 BOOL found;
2201 if (desc)
2203 FIXME( "description not supported\n" );
2204 return E_NOTIMPL;
2206 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2207 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
2208 return hr;
2210 switch (option)
2212 case WS_READ_REQUIRED_VALUE:
2213 if (!found) return WS_E_INVALID_FORMAT;
2214 if (size != sizeof(INT32)) return E_INVALIDARG;
2215 *(INT32 *)ret = val;
2216 break;
2218 case WS_READ_REQUIRED_POINTER:
2219 if (!found) return WS_E_INVALID_FORMAT;
2220 /* fall through */
2222 case WS_READ_OPTIONAL_POINTER:
2224 INT32 *heap_val = NULL;
2225 if (size != sizeof(heap_val)) return E_INVALIDARG;
2226 if (found)
2228 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2229 *heap_val = val;
2231 *(INT32 **)ret = heap_val;
2232 break;
2234 default:
2235 FIXME( "read option %u not supported\n", option );
2236 return E_NOTIMPL;
2239 return S_OK;
2242 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
2243 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2244 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
2245 WS_HEAP *heap, void *ret, ULONG size )
2247 WS_XML_UTF8_TEXT *utf8;
2248 HRESULT hr;
2249 INT64 val;
2250 BOOL found;
2252 if (desc)
2254 FIXME( "description not supported\n" );
2255 return E_NOTIMPL;
2257 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2258 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
2259 return hr;
2261 switch (option)
2263 case WS_READ_REQUIRED_VALUE:
2264 if (!found) return WS_E_INVALID_FORMAT;
2265 if (size != sizeof(INT64)) return E_INVALIDARG;
2266 *(INT64 *)ret = val;
2267 break;
2269 case WS_READ_REQUIRED_POINTER:
2270 if (!found) return WS_E_INVALID_FORMAT;
2271 /* fall through */
2273 case WS_READ_OPTIONAL_POINTER:
2275 INT64 *heap_val = NULL;
2276 if (size != sizeof(heap_val)) return E_INVALIDARG;
2277 if (found)
2279 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2280 *heap_val = val;
2282 *(INT64 **)ret = heap_val;
2283 break;
2285 default:
2286 FIXME( "read option %u not supported\n", option );
2287 return E_NOTIMPL;
2290 return S_OK;
2293 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
2294 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2295 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
2296 WS_HEAP *heap, void *ret, ULONG size )
2298 WS_XML_UTF8_TEXT *utf8;
2299 HRESULT hr;
2300 UINT64 val;
2301 BOOL found;
2303 if (desc)
2305 FIXME( "description not supported\n" );
2306 return E_NOTIMPL;
2308 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2309 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
2310 return hr;
2312 switch (option)
2314 case WS_READ_REQUIRED_VALUE:
2315 if (!found) return WS_E_INVALID_FORMAT;
2316 if (size != sizeof(UINT8)) return E_INVALIDARG;
2317 *(UINT8 *)ret = val;
2318 break;
2320 case WS_READ_REQUIRED_POINTER:
2321 if (!found) return WS_E_INVALID_FORMAT;
2322 /* fall through */
2324 case WS_READ_OPTIONAL_POINTER:
2326 UINT8 *heap_val = NULL;
2327 if (size != sizeof(heap_val)) return E_INVALIDARG;
2328 if (found)
2330 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2331 *heap_val = val;
2333 *(UINT8 **)ret = heap_val;
2334 break;
2336 default:
2337 FIXME( "read option %u not supported\n", option );
2338 return E_NOTIMPL;
2341 return S_OK;
2344 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
2345 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2346 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
2347 WS_HEAP *heap, void *ret, ULONG size )
2349 WS_XML_UTF8_TEXT *utf8;
2350 HRESULT hr;
2351 UINT64 val;
2352 BOOL found;
2354 if (desc)
2356 FIXME( "description not supported\n" );
2357 return E_NOTIMPL;
2359 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2360 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
2361 return hr;
2363 switch (option)
2365 case WS_READ_REQUIRED_VALUE:
2366 if (!found) return WS_E_INVALID_FORMAT;
2367 if (size != sizeof(UINT16)) return E_INVALIDARG;
2368 *(UINT16 *)ret = val;
2369 break;
2371 case WS_READ_REQUIRED_POINTER:
2372 if (!found) return WS_E_INVALID_FORMAT;
2373 /* fall through */
2375 case WS_READ_OPTIONAL_POINTER:
2377 UINT16 *heap_val = NULL;
2378 if (size != sizeof(heap_val)) return E_INVALIDARG;
2379 if (found)
2381 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2382 *heap_val = val;
2384 *(UINT16 **)ret = heap_val;
2385 break;
2387 default:
2388 FIXME( "read option %u not supported\n", option );
2389 return E_NOTIMPL;
2392 return S_OK;
2395 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
2396 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2397 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
2398 WS_HEAP *heap, void *ret, ULONG size )
2400 WS_XML_UTF8_TEXT *utf8;
2401 HRESULT hr;
2402 UINT64 val;
2403 BOOL found;
2405 if (desc)
2407 FIXME( "description not supported\n" );
2408 return E_NOTIMPL;
2410 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2411 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
2412 return hr;
2414 switch (option)
2416 case WS_READ_REQUIRED_VALUE:
2417 if (!found) return WS_E_INVALID_FORMAT;
2418 if (size != sizeof(UINT32)) return E_INVALIDARG;
2419 *(UINT32 *)ret = val;
2420 break;
2422 case WS_READ_REQUIRED_POINTER:
2423 if (!found) return WS_E_INVALID_FORMAT;
2424 /* fall through */
2426 case WS_READ_OPTIONAL_POINTER:
2428 UINT32 *heap_val = NULL;
2429 if (size != sizeof(heap_val)) return E_INVALIDARG;
2430 if (found)
2432 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2433 *heap_val = val;
2435 *(UINT32 **)ret = heap_val;
2436 break;
2438 default:
2439 FIXME( "read option %u not supported\n", option );
2440 return E_NOTIMPL;
2443 return S_OK;
2446 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
2447 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2448 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
2449 WS_HEAP *heap, void *ret, ULONG size )
2451 WS_XML_UTF8_TEXT *utf8;
2452 HRESULT hr;
2453 UINT64 val;
2454 BOOL found;
2456 if (desc)
2458 FIXME( "description not supported\n" );
2459 return E_NOTIMPL;
2461 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2462 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
2463 return hr;
2465 switch (option)
2467 case WS_READ_REQUIRED_VALUE:
2468 if (!found) return WS_E_INVALID_FORMAT;
2469 if (size != sizeof(UINT64)) return E_INVALIDARG;
2470 *(UINT64 *)ret = val;
2471 break;
2473 case WS_READ_REQUIRED_POINTER:
2474 if (!found) return WS_E_INVALID_FORMAT;
2475 /* fall through */
2477 case WS_READ_OPTIONAL_POINTER:
2479 UINT64 *heap_val = NULL;
2480 if (size != sizeof(heap_val)) return E_INVALIDARG;
2481 if (found)
2483 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2484 *heap_val = val;
2486 *(UINT64 **)ret = heap_val;
2487 break;
2489 default:
2490 FIXME( "read option %u not supported\n", option );
2491 return E_NOTIMPL;
2494 return S_OK;
2497 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
2498 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2499 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
2500 WS_HEAP *heap, WCHAR **ret, ULONG size )
2502 WS_XML_UTF8_TEXT *utf8;
2503 HRESULT hr;
2504 WCHAR *str = NULL;
2505 BOOL found;
2507 if (desc)
2509 FIXME( "description not supported\n" );
2510 return E_NOTIMPL;
2512 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2513 if (found && !(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
2515 switch (option)
2517 case WS_READ_REQUIRED_POINTER:
2518 if (!found) return WS_E_INVALID_FORMAT;
2519 /* fall through */
2521 case WS_READ_OPTIONAL_POINTER:
2522 if (size != sizeof(str)) return E_INVALIDARG;
2523 *ret = str;
2524 break;
2526 default:
2527 FIXME( "read option %u not supported\n", option );
2528 return E_NOTIMPL;
2531 return S_OK;
2534 static ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
2536 switch (type)
2538 case WS_INT8_TYPE:
2539 case WS_UINT8_TYPE:
2540 return sizeof(INT8);
2542 case WS_INT16_TYPE:
2543 case WS_UINT16_TYPE:
2544 return sizeof(INT16);
2546 case WS_BOOL_TYPE:
2547 case WS_INT32_TYPE:
2548 case WS_UINT32_TYPE:
2549 return sizeof(INT32);
2551 case WS_INT64_TYPE:
2552 case WS_UINT64_TYPE:
2553 return sizeof(INT64);
2555 case WS_WSZ_TYPE:
2556 return sizeof(WCHAR *);
2558 case WS_STRUCT_TYPE:
2559 return desc->size;
2561 default:
2562 ERR( "unhandled type %u\n", type );
2563 return 0;
2567 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
2568 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
2569 void *, ULONG );
2571 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
2572 WS_READ_OPTION option, WS_HEAP *heap, void **ret,
2573 ULONG size, ULONG *count )
2575 HRESULT hr;
2576 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
2577 char *buf;
2579 if (size != sizeof(void *)) return E_INVALIDARG;
2581 /* wrapper element */
2582 if (desc->localName && ((hr = read_node( reader )) != S_OK)) return hr;
2584 item_size = get_type_size( desc->type, desc->typeDescription );
2585 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
2586 for (;;)
2588 if (nb_items >= nb_allocated)
2590 if (!(buf = ws_realloc_zero( heap, buf, nb_allocated * 2 * item_size )))
2591 return WS_E_QUOTA_EXCEEDED;
2592 nb_allocated *= 2;
2594 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
2595 desc->typeDescription, WS_READ_REQUIRED_VALUE, heap, buf + offset, item_size );
2596 if (hr == WS_E_INVALID_FORMAT) break;
2597 if (hr != S_OK)
2599 ws_free( heap, buf );
2600 return hr;
2602 if ((hr = read_node( reader )) != S_OK)
2604 ws_free( heap, buf );
2605 return hr;
2607 offset += item_size;
2608 nb_items++;
2611 if (desc->localName && ((hr = read_node( reader )) != S_OK)) return hr;
2613 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
2615 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
2616 desc->itemRange->maxItemCount );
2617 ws_free( heap, buf );
2618 return WS_E_INVALID_FORMAT;
2621 *count = nb_items;
2622 *ret = buf;
2624 return S_OK;
2627 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
2628 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
2630 HRESULT hr;
2631 BOOL found;
2633 if ((hr = read_to_startelement( reader, &found )) != S_OK) return S_OK;
2634 if (!found) return WS_E_INVALID_FORMAT;
2635 if ((hr = read_node( reader )) != S_OK) return hr;
2637 return read_type( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, desc->type, NULL, NULL,
2638 desc->typeDescription, option, heap, ret, size );
2641 static WS_READ_OPTION map_field_options( WS_TYPE type, ULONG options )
2643 if (options & !(WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
2645 FIXME( "options %08x not supported\n", options );
2646 return 0;
2649 switch (type)
2651 case WS_BOOL_TYPE:
2652 case WS_INT8_TYPE:
2653 case WS_INT16_TYPE:
2654 case WS_INT32_TYPE:
2655 case WS_INT64_TYPE:
2656 case WS_UINT8_TYPE:
2657 case WS_UINT16_TYPE:
2658 case WS_UINT32_TYPE:
2659 case WS_UINT64_TYPE:
2660 return WS_READ_REQUIRED_VALUE;
2662 case WS_WSZ_TYPE:
2663 case WS_STRUCT_TYPE:
2664 return WS_READ_REQUIRED_POINTER;
2666 default:
2667 FIXME( "unhandled type %u\n", type );
2668 return 0;
2672 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
2673 WS_HEAP *heap, char *buf )
2675 char *ptr = buf + desc->offset;
2676 WS_READ_OPTION option;
2677 ULONG size;
2678 HRESULT hr;
2680 if (!(option = map_field_options( desc->type, desc->options ))) return E_INVALIDARG;
2682 if (option == WS_READ_REQUIRED_VALUE)
2683 size = get_type_size( desc->type, desc->typeDescription );
2684 else
2685 size = sizeof(void *);
2687 switch (desc->mapping)
2689 case WS_ATTRIBUTE_FIELD_MAPPING:
2690 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
2691 desc->typeDescription, option, heap, ptr, size );
2692 break;
2694 case WS_ELEMENT_FIELD_MAPPING:
2695 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
2696 desc->typeDescription, option, heap, ptr, size );
2697 break;
2699 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
2701 ULONG count;
2702 hr = read_type_repeating_element( reader, desc, option, heap, (void **)ptr, size, &count );
2703 if (hr == S_OK) *(ULONG *)(ptr + desc->countOffset) = count;
2704 break;
2706 case WS_TEXT_FIELD_MAPPING:
2707 hr = read_type_text( reader, desc, option, heap, ptr, size );
2708 break;
2710 default:
2711 FIXME( "unhandled field mapping %u\n", desc->mapping );
2712 return E_NOTIMPL;
2716 if (hr == WS_E_INVALID_FORMAT && desc->options & WS_FIELD_OPTIONAL)
2718 switch (option)
2720 case WS_READ_REQUIRED_VALUE:
2721 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
2722 else memset( ptr, 0, size );
2723 return S_OK;
2725 case WS_READ_REQUIRED_POINTER:
2726 *(void **)ptr = NULL;
2727 return S_OK;
2729 default:
2730 ERR( "unhandled option %u\n", option );
2731 return E_NOTIMPL;
2735 return hr;
2738 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
2739 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2740 const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
2741 WS_HEAP *heap, void *ret, ULONG size )
2743 ULONG i;
2744 HRESULT hr;
2745 char *buf;
2747 if (!desc) return E_INVALIDARG;
2749 if (desc->structOptions)
2751 FIXME( "struct options %08x not supported\n", desc->structOptions );
2752 return E_NOTIMPL;
2755 switch (option)
2757 case WS_READ_REQUIRED_POINTER:
2758 case WS_READ_OPTIONAL_POINTER:
2759 if (size != sizeof(void *)) return E_INVALIDARG;
2760 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
2761 break;
2763 case WS_READ_REQUIRED_VALUE:
2764 if (size != desc->size) return E_INVALIDARG;
2765 buf = ret;
2766 break;
2768 default:
2769 FIXME( "unhandled read option %u\n", option );
2770 return E_NOTIMPL;
2773 for (i = 0; i < desc->fieldCount; i++)
2775 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
2776 break;
2779 switch (option)
2781 case WS_READ_REQUIRED_POINTER:
2782 if (hr != S_OK)
2784 ws_free( heap, buf );
2785 return hr;
2787 *(char **)ret = buf;
2788 return S_OK;
2790 case WS_READ_OPTIONAL_POINTER:
2791 if (hr != S_OK)
2793 ws_free( heap, buf );
2794 buf = NULL;
2796 *(char **)ret = buf;
2797 return S_OK;
2799 case WS_READ_REQUIRED_VALUE:
2800 return hr;
2802 default:
2803 ERR( "unhandled read option %u\n", option );
2804 return E_NOTIMPL;
2808 static BOOL is_empty_text_node( const struct node *node )
2810 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
2811 const WS_XML_UTF8_TEXT *utf8;
2812 ULONG i;
2814 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
2815 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
2817 ERR( "unhandled text type %u\n", text->text->textType );
2818 return FALSE;
2820 utf8 = (const WS_XML_UTF8_TEXT *)text->text;
2821 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
2822 return TRUE;
2825 static HRESULT read_type_next_node( struct reader *reader, const WS_XML_STRING *localname,
2826 const WS_XML_STRING *ns )
2828 const WS_XML_ELEMENT_NODE *elem;
2829 WS_XML_NODE_TYPE type;
2830 HRESULT hr;
2831 BOOL found;
2833 if (!localname) return S_OK; /* assume reader is already correctly positioned */
2834 if ((hr = read_to_startelement( reader, &found ) != S_OK)) return hr;
2835 if (!found) return WS_E_INVALID_FORMAT;
2837 elem = &reader->current->hdr;
2838 if (WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
2839 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK) return S_OK;
2841 for (;;)
2843 if ((hr = read_node( reader ) != S_OK)) return hr;
2844 type = node_type( reader->current );
2845 if (type == WS_XML_NODE_TYPE_COMMENT ||
2846 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
2847 break;
2850 return S_OK;
2853 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
2854 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2855 const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
2856 void *value, ULONG size )
2858 HRESULT hr;
2860 switch (mapping)
2862 case WS_ELEMENT_TYPE_MAPPING:
2863 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2864 if ((hr = read_type_next_node( reader, localname, ns )) != S_OK) return hr;
2865 break;
2867 case WS_ATTRIBUTE_TYPE_MAPPING:
2868 break;
2870 default:
2871 FIXME( "unhandled mapping %u\n", mapping );
2872 return E_NOTIMPL;
2875 switch (type)
2877 case WS_STRUCT_TYPE:
2878 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2879 return hr;
2880 break;
2882 case WS_BOOL_TYPE:
2883 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2884 return hr;
2885 break;
2887 case WS_INT8_TYPE:
2888 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2889 return hr;
2890 break;
2892 case WS_INT16_TYPE:
2893 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2894 return hr;
2895 break;
2897 case WS_INT32_TYPE:
2898 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2899 return hr;
2900 break;
2902 case WS_INT64_TYPE:
2903 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2904 return hr;
2905 break;
2907 case WS_UINT8_TYPE:
2908 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2909 return hr;
2910 break;
2912 case WS_UINT16_TYPE:
2913 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2914 return hr;
2915 break;
2917 case WS_UINT32_TYPE:
2918 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2919 return hr;
2920 break;
2922 case WS_UINT64_TYPE:
2923 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2924 return hr;
2925 break;
2927 case WS_WSZ_TYPE:
2928 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
2929 return hr;
2930 break;
2932 default:
2933 FIXME( "type %u not supported\n", type );
2934 return E_NOTIMPL;
2937 switch (mapping)
2939 case WS_ELEMENT_TYPE_MAPPING:
2940 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2941 return read_node( reader );
2943 case WS_ATTRIBUTE_TYPE_MAPPING:
2944 default:
2945 return S_OK;
2949 /**************************************************************************
2950 * WsReadType [webservices.@]
2952 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
2953 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
2954 ULONG size, WS_ERROR *error )
2956 struct reader *reader = (struct reader *)handle;
2957 HRESULT hr;
2959 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
2960 size, error );
2961 if (error) FIXME( "ignoring error parameter\n" );
2963 if (!reader || !value) return E_INVALIDARG;
2965 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
2966 return hr;
2968 if ((hr = read_node( reader )) != S_OK) return hr;
2969 if (!read_end_of_data( reader )) return WS_E_INVALID_FORMAT;
2970 return S_OK;
2973 /**************************************************************************
2974 * WsSetErrorProperty [webservices.@]
2976 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
2977 ULONG size )
2979 struct error *error = (struct error *)handle;
2981 TRACE( "%p %u %p %u\n", handle, id, value, size );
2983 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
2984 return set_error_prop( error, id, value, size );
2987 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
2989 static const char bom[] = {0xef,0xbb,0xbf};
2990 const unsigned char *p = data;
2992 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
2993 (size > 2 && !(*offset = 0));
2996 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
2998 static const char bom[] = {0xff,0xfe};
2999 const unsigned char *p = data;
3001 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
3002 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
3005 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
3007 WS_CHARSET ret = 0;
3009 /* FIXME: parse xml declaration */
3011 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
3012 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
3013 else
3015 FIXME( "charset not recognized\n" );
3016 return 0;
3019 TRACE( "detected charset %u\n", ret );
3020 return ret;
3023 static void set_input_buffer( struct reader *reader, const unsigned char *data, ULONG size )
3025 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
3026 reader->input_data = data;
3027 reader->input_size = size;
3029 reader->read_size = reader->input_size;
3030 reader->read_pos = 0;
3031 reader->read_bufptr = reader->input_data;
3034 /**************************************************************************
3035 * WsSetInput [webservices.@]
3037 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
3038 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
3039 ULONG count, WS_ERROR *error )
3041 struct reader *reader = (struct reader *)handle;
3042 struct node *node;
3043 HRESULT hr;
3044 ULONG i, offset = 0;
3046 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
3047 if (error) FIXME( "ignoring error parameter\n" );
3049 if (!reader) return E_INVALIDARG;
3051 for (i = 0; i < count; i++)
3053 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
3054 if (hr != S_OK) return hr;
3057 if ((hr = read_init_state( reader )) != S_OK) return hr;
3059 switch (encoding->encodingType)
3061 case WS_XML_READER_ENCODING_TYPE_TEXT:
3063 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
3064 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
3065 WS_CHARSET charset = text->charSet;
3067 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
3069 FIXME( "charset detection on input type %u not supported\n", input->inputType );
3070 return E_NOTIMPL;
3073 if (charset == WS_CHARSET_AUTO)
3074 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
3076 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
3077 if (hr != S_OK) return hr;
3078 break;
3080 default:
3081 FIXME( "encoding type %u not supported\n", encoding->encodingType );
3082 return E_NOTIMPL;
3084 switch (input->inputType)
3086 case WS_XML_READER_INPUT_TYPE_BUFFER:
3088 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
3089 set_input_buffer( reader, (const unsigned char *)buf->encodedData + offset, buf->encodedDataSize - offset );
3090 break;
3092 default:
3093 FIXME( "input type %u not supported\n", input->inputType );
3094 return E_NOTIMPL;
3097 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
3098 read_insert_bof( reader, node );
3099 return S_OK;
3102 /**************************************************************************
3103 * WsSetInputToBuffer [webservices.@]
3105 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
3106 const WS_XML_READER_PROPERTY *properties, ULONG count,
3107 WS_ERROR *error )
3109 struct reader *reader = (struct reader *)handle;
3110 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
3111 WS_CHARSET charset;
3112 struct node *node;
3113 HRESULT hr;
3114 ULONG i, offset = 0;
3116 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
3117 if (error) FIXME( "ignoring error parameter\n" );
3119 if (!reader || !xmlbuf) return E_INVALIDARG;
3121 for (i = 0; i < count; i++)
3123 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
3124 if (hr != S_OK) return hr;
3127 if ((hr = read_init_state( reader )) != S_OK) return hr;
3129 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
3130 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
3131 if (hr != S_OK) return hr;
3133 set_input_buffer( reader, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
3134 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
3135 read_insert_bof( reader, node );
3136 return S_OK;
3139 /**************************************************************************
3140 * WsXmlStringEquals [webservices.@]
3142 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
3144 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
3145 if (error) FIXME( "ignoring error parameter\n" );
3147 if (!str1 || !str2) return E_INVALIDARG;
3149 if (str1->length != str2->length) return S_FALSE;
3150 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
3151 return S_FALSE;