webservices: Implement WsReadElement.
[wine.git] / dlls / webservices / reader.c
blobc79f8cce76dbe124a48ee75468c853b8c964ed42
1 /*
2 * Copyright 2015, 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winnls.h"
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "webservices_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
32 const char *debugstr_xmlstr( const WS_XML_STRING *str )
34 if (!str) return "(null)";
35 return debugstr_an( (const char *)str->bytes, str->length );
38 ULONG prop_size( const struct prop_desc *desc, ULONG count )
40 ULONG i, ret = count * sizeof(struct prop);
41 for (i = 0; i < count; i++) ret += desc[i].size;
42 return ret;
45 void prop_init( const struct prop_desc *desc, ULONG count, struct prop *prop, void *data )
47 ULONG i;
48 char *ptr = data;
49 for (i = 0; i < count; i++)
51 prop[i].value = ptr;
52 prop[i].size = desc[i].size;
53 prop[i].readonly = desc[i].readonly;
54 prop[i].writeonly = desc[i].writeonly;
55 ptr += prop[i].size;
59 HRESULT prop_set( const struct prop *prop, ULONG count, ULONG id, const void *value, ULONG size )
61 if (id >= count || size != prop[id].size || prop[id].readonly) return E_INVALIDARG;
62 memcpy( prop[id].value, value, size );
63 return S_OK;
66 HRESULT prop_get( const struct prop *prop, ULONG count, ULONG id, void *buf, ULONG size )
68 if (id >= count || size != prop[id].size || prop[id].writeonly) return E_INVALIDARG;
69 memcpy( buf, prop[id].value, prop[id].size );
70 return S_OK;
73 static const struct prop_desc error_props[] =
75 { sizeof(ULONG), TRUE }, /* WS_ERROR_PROPERTY_STRING_COUNT */
76 { sizeof(ULONG), FALSE }, /* WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE */
77 { sizeof(LANGID), FALSE } /* WS_ERROR_PROPERTY_LANGID */
80 struct error
82 ULONG prop_count;
83 struct prop prop[sizeof(error_props)/sizeof(error_props[0])];
86 static struct error *alloc_error(void)
88 static const ULONG count = sizeof(error_props)/sizeof(error_props[0]);
89 struct error *ret;
90 ULONG size = sizeof(*ret) + prop_size( error_props, count );
92 if (!(ret = heap_alloc_zero( size ))) return NULL;
93 prop_init( error_props, count, ret->prop, &ret[1] );
94 ret->prop_count = count;
95 return ret;
98 /**************************************************************************
99 * WsCreateError [webservices.@]
101 HRESULT WINAPI WsCreateError( const WS_ERROR_PROPERTY *properties, ULONG count, WS_ERROR **handle )
103 struct error *error;
104 LANGID langid = GetUserDefaultUILanguage();
105 HRESULT hr;
106 ULONG i;
108 TRACE( "%p %u %p\n", properties, count, handle );
110 if (!handle) return E_INVALIDARG;
111 if (!(error = alloc_error())) return E_OUTOFMEMORY;
113 prop_set( error->prop, error->prop_count, WS_ERROR_PROPERTY_LANGID, &langid, sizeof(langid) );
114 for (i = 0; i < count; i++)
116 if (properties[i].id == WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE)
118 heap_free( error );
119 return E_INVALIDARG;
121 hr = prop_set( error->prop, error->prop_count, properties[i].id, properties[i].value,
122 properties[i].valueSize );
123 if (hr != S_OK)
125 heap_free( error );
126 return hr;
130 *handle = (WS_ERROR *)error;
131 return S_OK;
134 /**************************************************************************
135 * WsFreeError [webservices.@]
137 void WINAPI WsFreeError( WS_ERROR *handle )
139 struct error *error = (struct error *)handle;
141 TRACE( "%p\n", handle );
142 heap_free( error );
145 static const struct prop_desc heap_props[] =
147 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_MAX_SIZE */
148 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_TRIM_SIZE */
149 { sizeof(SIZE_T), TRUE }, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
150 { sizeof(SIZE_T), TRUE } /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
153 struct heap
155 HANDLE handle;
156 ULONG prop_count;
157 struct prop prop[sizeof(heap_props)/sizeof(heap_props[0])];
160 static BOOL ensure_heap( struct heap *heap )
162 SIZE_T size;
163 if (heap->handle) return TRUE;
164 if (prop_get( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_MAX_SIZE, &size, sizeof(size) ) != S_OK)
165 return FALSE;
166 if (!(heap->handle = HeapCreate( 0, 0, size ))) return FALSE;
167 return TRUE;
170 void *ws_alloc( WS_HEAP *handle, SIZE_T size )
172 struct heap *heap = (struct heap *)handle;
173 if (!ensure_heap( heap )) return NULL;
174 return HeapAlloc( heap->handle, 0, size );
177 static void *ws_alloc_zero( WS_HEAP *handle, SIZE_T size )
179 struct heap *heap = (struct heap *)handle;
180 if (!ensure_heap( heap )) return NULL;
181 return HeapAlloc( heap->handle, HEAP_ZERO_MEMORY, size );
184 void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
186 struct heap *heap = (struct heap *)handle;
187 if (!ensure_heap( heap )) return NULL;
188 return HeapReAlloc( heap->handle, 0, ptr, size );
191 static void *ws_realloc_zero( WS_HEAP *handle, void *ptr, SIZE_T size )
193 struct heap *heap = (struct heap *)handle;
194 if (!ensure_heap( heap )) return NULL;
195 return HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, size );
198 void ws_free( WS_HEAP *handle, void *ptr )
200 struct heap *heap = (struct heap *)handle;
201 if (!heap->handle) return;
202 HeapFree( heap->handle, 0, ptr );
205 /**************************************************************************
206 * WsAlloc [webservices.@]
208 HRESULT WINAPI WsAlloc( WS_HEAP *handle, SIZE_T size, void **ptr, WS_ERROR *error )
210 void *mem;
212 TRACE( "%p %u %p %p\n", handle, (ULONG)size, ptr, error );
213 if (error) FIXME( "ignoring error parameter\n" );
215 if (!handle || !ptr) return E_INVALIDARG;
217 if (!(mem = ws_alloc( handle, size ))) return E_OUTOFMEMORY;
218 *ptr = mem;
219 return S_OK;
222 static struct heap *alloc_heap(void)
224 static const ULONG count = sizeof(heap_props)/sizeof(heap_props[0]);
225 struct heap *ret;
226 ULONG size = sizeof(*ret) + prop_size( heap_props, count );
228 if (!(ret = heap_alloc_zero( size ))) return NULL;
229 prop_init( heap_props, count, ret->prop, &ret[1] );
230 ret->prop_count = count;
231 return ret;
234 /**************************************************************************
235 * WsCreateHeap [webservices.@]
237 HRESULT WINAPI WsCreateHeap( SIZE_T max_size, SIZE_T trim_size, const WS_HEAP_PROPERTY *properties,
238 ULONG count, WS_HEAP **handle, WS_ERROR *error )
240 struct heap *heap;
242 TRACE( "%u %u %p %u %p %p\n", (ULONG)max_size, (ULONG)trim_size, properties, count, handle, error );
243 if (error) FIXME( "ignoring error parameter\n" );
245 if (!handle || count) return E_INVALIDARG;
246 if (!(heap = alloc_heap())) return E_OUTOFMEMORY;
248 prop_set( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_MAX_SIZE, &max_size, sizeof(max_size) );
249 prop_set( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_TRIM_SIZE, &trim_size, sizeof(trim_size) );
251 *handle = (WS_HEAP *)heap;
252 return S_OK;
255 /**************************************************************************
256 * WsFreeHeap [webservices.@]
258 void WINAPI WsFreeHeap( WS_HEAP *handle )
260 struct heap *heap = (struct heap *)handle;
262 TRACE( "%p\n", handle );
264 if (!heap) return;
265 HeapDestroy( heap->handle );
266 heap_free( heap );
269 /**************************************************************************
270 * WsResetHeap [webservices.@]
272 HRESULT WINAPI WsResetHeap( WS_HEAP *handle, WS_ERROR *error )
274 struct heap *heap = (struct heap *)handle;
276 TRACE( "%p %p\n", handle, error );
277 if (error) FIXME( "ignoring error parameter\n" );
279 if (!heap) return E_INVALIDARG;
281 HeapDestroy( heap->handle );
282 heap->handle = NULL;
283 return S_OK;
286 struct node *alloc_node( WS_XML_NODE_TYPE type )
288 struct node *ret;
290 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
291 ret->hdr.node.nodeType = type;
292 list_init( &ret->entry );
293 list_init( &ret->children );
294 return ret;
297 void free_attribute( WS_XML_ATTRIBUTE *attr )
299 if (!attr) return;
300 heap_free( attr->prefix );
301 heap_free( attr->localName );
302 heap_free( attr->ns );
303 heap_free( attr->value );
304 heap_free( attr );
307 void free_node( struct node *node )
309 if (!node) return;
310 switch (node_type( node ))
312 case WS_XML_NODE_TYPE_ELEMENT:
314 WS_XML_ELEMENT_NODE *elem = &node->hdr;
315 ULONG i;
317 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
318 heap_free( elem->attributes );
319 heap_free( elem->prefix );
320 heap_free( elem->localName );
321 heap_free( elem->ns );
322 break;
324 case WS_XML_NODE_TYPE_TEXT:
326 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
327 heap_free( text->text );
328 break;
330 case WS_XML_NODE_TYPE_COMMENT:
332 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
333 heap_free( comment->value.bytes );
334 break;
336 case WS_XML_NODE_TYPE_CDATA:
337 case WS_XML_NODE_TYPE_END_CDATA:
338 case WS_XML_NODE_TYPE_END_ELEMENT:
339 case WS_XML_NODE_TYPE_EOF:
340 case WS_XML_NODE_TYPE_BOF:
341 break;
343 default:
344 ERR( "unhandled type %u\n", node_type( node ) );
345 break;
347 heap_free( node );
350 void destroy_nodes( struct node *node )
352 struct list *ptr;
354 if (!node) return;
355 while ((ptr = list_head( &node->children )))
357 struct node *child = LIST_ENTRY( ptr, struct node, entry );
358 list_remove( &child->entry );
359 destroy_nodes( child );
361 free_node( node );
364 static const struct prop_desc reader_props[] =
366 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
367 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
368 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
369 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
370 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
371 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
372 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
373 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
374 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
375 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
376 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
377 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
378 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
379 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
380 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
383 enum reader_state
385 READER_STATE_INITIAL,
386 READER_STATE_BOF,
387 READER_STATE_STARTELEMENT,
388 READER_STATE_STARTATTRIBUTE,
389 READER_STATE_STARTCDATA,
390 READER_STATE_CDATA,
391 READER_STATE_TEXT,
392 READER_STATE_ENDELEMENT,
393 READER_STATE_ENDCDATA,
394 READER_STATE_COMMENT,
395 READER_STATE_EOF
398 struct prefix
400 WS_XML_STRING str;
401 WS_XML_STRING ns;
404 struct reader
406 ULONG read_size;
407 ULONG read_pos;
408 const unsigned char *read_bufptr;
409 enum reader_state state;
410 struct node *root;
411 struct node *current;
412 ULONG current_attr;
413 struct node *last;
414 struct prefix *prefixes;
415 ULONG nb_prefixes;
416 ULONG nb_prefixes_allocated;
417 WS_XML_READER_INPUT_TYPE input_type;
418 const unsigned char *input_data;
419 ULONG input_size;
420 ULONG prop_count;
421 struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])];
424 static struct reader *alloc_reader(void)
426 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
427 struct reader *ret;
428 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
430 if (!(ret = heap_alloc_zero( size ))) return NULL;
431 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
433 heap_free( ret );
434 return NULL;
436 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
438 prop_init( reader_props, count, ret->prop, &ret[1] );
439 ret->prop_count = count;
440 return ret;
443 static void clear_prefixes( struct prefix *prefixes, ULONG count )
445 ULONG i;
446 for (i = 0; i < count; i++)
448 heap_free( prefixes[i].str.bytes );
449 prefixes[i].str.bytes = NULL;
450 prefixes[i].str.length = 0;
452 heap_free( prefixes[i].ns.bytes );
453 prefixes[i].ns.bytes = NULL;
454 prefixes[i].ns.length = 0;
458 static void free_reader( struct reader *reader )
460 if (!reader) return;
461 destroy_nodes( reader->root );
462 clear_prefixes( reader->prefixes, reader->nb_prefixes );
463 heap_free( reader->prefixes );
464 heap_free( reader );
467 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
469 if (str)
471 heap_free( prefix->str.bytes );
472 if (!(prefix->str.bytes = heap_alloc( str->length ))) return E_OUTOFMEMORY;
473 memcpy( prefix->str.bytes, str->bytes, str->length );
474 prefix->str.length = str->length;
477 heap_free( prefix->ns.bytes );
478 if (!(prefix->ns.bytes = heap_alloc( ns->length ))) return E_OUTOFMEMORY;
479 memcpy( prefix->ns.bytes, ns->bytes, ns->length );
480 prefix->ns.length = ns->length;
482 return S_OK;
485 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
487 ULONG i;
488 HRESULT hr;
490 for (i = 0; i < reader->nb_prefixes; i++)
492 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
493 return set_prefix( &reader->prefixes[i], NULL, ns );
495 if (i >= reader->nb_prefixes_allocated)
497 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
498 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
499 if (!tmp) return E_OUTOFMEMORY;
500 reader->prefixes = tmp;
501 reader->nb_prefixes_allocated *= 2;
504 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
505 reader->nb_prefixes++;
506 return S_OK;
509 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
511 ULONG i;
512 for (i = 0; i < reader->nb_prefixes; i++)
514 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
515 return &reader->prefixes[i].ns;
517 return NULL;
520 static void read_insert_eof( struct reader *reader, struct node *eof )
522 if (!reader->root) reader->root = eof;
523 else
525 eof->parent = reader->root;
526 list_add_tail( &reader->root->children, &eof->entry );
528 reader->current = reader->last = eof;
531 static void read_insert_bof( struct reader *reader, struct node *bof )
533 reader->root->parent = bof;
534 list_add_tail( &bof->children, &reader->root->entry );
535 reader->current = reader->last = reader->root = bof;
538 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
540 node->parent = parent;
541 if (node->parent == reader->root)
543 struct list *eof = list_tail( &reader->root->children );
544 list_add_before( eof, &node->entry );
546 else list_add_tail( &parent->children, &node->entry );
547 reader->current = reader->last = node;
550 static HRESULT read_init_state( struct reader *reader )
552 struct node *node;
554 destroy_nodes( reader->root );
555 reader->root = NULL;
556 clear_prefixes( reader->prefixes, reader->nb_prefixes );
557 reader->nb_prefixes = 1;
558 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
559 read_insert_eof( reader, node );
560 reader->state = READER_STATE_INITIAL;
561 return S_OK;
564 /**************************************************************************
565 * WsCreateReader [webservices.@]
567 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
568 WS_XML_READER **handle, WS_ERROR *error )
570 struct reader *reader;
571 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
572 WS_CHARSET charset = WS_CHARSET_UTF8;
573 BOOL read_decl = TRUE;
574 HRESULT hr;
576 TRACE( "%p %u %p %p\n", properties, count, handle, error );
577 if (error) FIXME( "ignoring error parameter\n" );
579 if (!handle) return E_INVALIDARG;
580 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
582 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
583 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
584 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
585 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
586 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
588 for (i = 0; i < count; i++)
590 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
591 properties[i].valueSize );
592 if (hr != S_OK)
594 free_reader( reader );
595 return hr;
599 if ((hr = read_init_state( reader )) != S_OK)
601 free_reader( reader );
602 return hr;
605 *handle = (WS_XML_READER *)reader;
606 return S_OK;
609 /**************************************************************************
610 * WsFreeReader [webservices.@]
612 void WINAPI WsFreeReader( WS_XML_READER *handle )
614 struct reader *reader = (struct reader *)handle;
616 TRACE( "%p\n", handle );
617 free_reader( reader );
620 /**************************************************************************
621 * WsFillReader [webservices.@]
623 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
624 WS_ERROR *error )
626 struct reader *reader = (struct reader *)handle;
628 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
629 if (error) FIXME( "ignoring error parameter\n" );
631 if (!reader) return E_INVALIDARG;
633 /* FIXME: add support for stream input */
634 reader->read_size = min( min_size, reader->input_size );
635 reader->read_pos = 0;
637 return S_OK;
640 /**************************************************************************
641 * WsGetErrorProperty [webservices.@]
643 HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf,
644 ULONG size )
646 struct error *error = (struct error *)handle;
648 TRACE( "%p %u %p %u\n", handle, id, buf, size );
649 return prop_get( error->prop, error->prop_count, id, buf, size );
652 /**************************************************************************
653 * WsGetErrorString [webservices.@]
655 HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str )
657 FIXME( "%p %u %p: stub\n", handle, index, str );
658 return E_NOTIMPL;
661 /**************************************************************************
662 * WsGetHeapProperty [webservices.@]
664 HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
665 ULONG size, WS_ERROR *error )
667 struct heap *heap = (struct heap *)handle;
669 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
670 if (error) FIXME( "ignoring error parameter\n" );
672 return prop_get( heap->prop, heap->prop_count, id, buf, size );
675 /**************************************************************************
676 * WsGetNamespaceFromPrefix [webservices.@]
678 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
679 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
681 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
682 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
683 static const WS_XML_STRING empty_ns = {0, NULL};
684 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
685 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
686 struct reader *reader = (struct reader *)handle;
687 BOOL found = FALSE;
689 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
690 if (error) FIXME( "ignoring error parameter\n" );
692 if (!reader || !prefix || !ns) return E_INVALIDARG;
693 if (reader->state != READER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
695 if (!prefix->length)
697 *ns = &empty_ns;
698 found = TRUE;
700 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
702 *ns = &xml_ns;
703 found = TRUE;
705 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
707 *ns = &xmlns_ns;
708 found = TRUE;
710 else
712 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
713 ULONG i;
715 for (i = 0; i < elem->attributeCount; i++)
717 if (!elem->attributes[i]->isXmlNs) continue;
718 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
720 *ns = elem->attributes[i]->ns;
721 found = TRUE;
722 break;
727 if (!found)
729 if (required) return WS_E_INVALID_FORMAT;
730 *ns = NULL;
731 return S_FALSE;
733 return S_OK;
736 /**************************************************************************
737 * WsGetReaderNode [webservices.@]
739 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
740 WS_ERROR *error )
742 struct reader *reader = (struct reader *)handle;
744 TRACE( "%p %p %p\n", handle, node, error );
745 if (error) FIXME( "ignoring error parameter\n" );
747 if (!reader || !node) return E_INVALIDARG;
749 *node = &reader->current->hdr.node;
750 return S_OK;
753 /**************************************************************************
754 * WsGetReaderProperty [webservices.@]
756 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
757 void *buf, ULONG size, WS_ERROR *error )
759 struct reader *reader = (struct reader *)handle;
761 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
762 if (error) FIXME( "ignoring error parameter\n" );
764 if (!reader->input_type) return WS_E_INVALID_OPERATION;
766 if (id == WS_XML_READER_PROPERTY_CHARSET)
768 WS_CHARSET charset;
769 HRESULT hr;
771 if ((hr = prop_get( reader->prop, reader->prop_count, id, &charset, size )) != S_OK) return hr;
772 if (!charset) return WS_E_INVALID_FORMAT;
773 *(WS_CHARSET *)buf = charset;
774 return S_OK;
776 return prop_get( reader->prop, reader->prop_count, id, buf, size );
779 /**************************************************************************
780 * WsGetXmlAttribute [webservices.@]
782 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
783 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
785 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
786 return E_NOTIMPL;
789 WS_XML_STRING *alloc_xml_string( const unsigned char *data, ULONG len )
791 WS_XML_STRING *ret;
793 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
794 ret->length = len;
795 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
796 ret->dictionary = NULL;
797 ret->id = 0;
798 if (data) memcpy( ret->bytes, data, len );
799 return ret;
802 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *data, ULONG len )
804 WS_XML_UTF8_TEXT *ret;
806 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
807 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
808 ret->value.length = len;
809 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
810 ret->value.dictionary = NULL;
811 ret->value.id = 0;
812 if (data) memcpy( ret->value.bytes, data, len );
813 return ret;
816 static inline BOOL read_end_of_data( struct reader *reader )
818 return reader->read_pos >= reader->read_size;
821 static inline const unsigned char *read_current_ptr( struct reader *reader )
823 return &reader->read_bufptr[reader->read_pos];
826 /* UTF-8 support based on libs/wine/utf8.c */
828 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
829 static const char utf8_length[128] =
831 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
832 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
833 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
834 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
835 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
836 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
837 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
838 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
841 /* first byte mask depending on UTF-8 sequence length */
842 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
844 /* minimum Unicode value depending on UTF-8 sequence length */
845 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
847 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
849 unsigned int len, res;
850 unsigned char ch = reader->read_bufptr[reader->read_pos];
851 const unsigned char *end;
853 if (reader->read_pos >= reader->read_size) return 0;
855 if (ch < 0x80)
857 *skip = 1;
858 return ch;
860 len = utf8_length[ch - 0x80];
861 if (reader->read_pos + len >= reader->read_size) return 0;
862 end = reader->read_bufptr + reader->read_pos + len;
863 res = ch & utf8_mask[len];
865 switch (len)
867 case 3:
868 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
869 res = (res << 6) | ch;
870 case 2:
871 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
872 res = (res << 6) | ch;
873 case 1:
874 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
875 res = (res << 6) | ch;
876 if (res < utf8_minval[len]) break;
877 *skip = len + 1;
878 return res;
881 return 0;
884 static inline void read_skip( struct reader *reader, unsigned int count )
886 if (reader->read_pos + count > reader->read_size) return;
887 reader->read_pos += count;
890 static inline void read_rewind( struct reader *reader, unsigned int count )
892 reader->read_pos -= count;
895 static inline BOOL read_isnamechar( unsigned int ch )
897 /* FIXME: incomplete */
898 return (ch >= 'A' && ch <= 'Z') ||
899 (ch >= 'a' && ch <= 'z') ||
900 (ch >= '0' && ch <= '9') ||
901 ch == '_' || ch == '-' || ch == '.' || ch == ':';
904 static inline BOOL read_isspace( unsigned int ch )
906 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
909 static inline void read_skip_whitespace( struct reader *reader )
911 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
912 reader->read_pos++;
915 static inline int read_cmp( struct reader *reader, const char *str, int len )
917 const unsigned char *ptr = read_current_ptr( reader );
919 if (len < 0) len = strlen( str );
920 if (reader->read_pos + len > reader->read_size) return -1;
921 while (len--)
923 if (*str != *ptr) return *ptr - *str;
924 str++; ptr++;
926 return 0;
929 static HRESULT read_xmldecl( struct reader *reader )
931 if (!reader->read_size) return WS_E_INVALID_FORMAT;
933 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
935 reader->state = READER_STATE_BOF;
936 return S_OK;
938 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
939 read_skip( reader, 6 );
941 /* FIXME: parse attributes */
942 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
943 reader->read_pos++;
945 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
946 read_skip( reader, 2 );
948 reader->state = READER_STATE_BOF;
949 return S_OK;
952 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
954 if (elem->attributeCount)
956 WS_XML_ATTRIBUTE **tmp;
957 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
958 return E_OUTOFMEMORY;
959 elem->attributes = tmp;
961 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
962 elem->attributes[elem->attributeCount++] = attr;
963 return S_OK;
966 static HRESULT parse_name( const unsigned char *str, unsigned int len,
967 WS_XML_STRING **prefix, WS_XML_STRING **localname )
969 const unsigned char *name_ptr = str, *prefix_ptr = NULL;
970 unsigned int i, name_len = len, prefix_len = 0;
972 for (i = 0; i < len; i++)
974 if (str[i] == ':')
976 prefix_ptr = str;
977 prefix_len = i;
978 name_ptr = &str[i + 1];
979 name_len -= i + 1;
980 break;
983 if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
984 if (!(*localname = alloc_xml_string( name_ptr, name_len )))
986 heap_free( *prefix );
987 return E_OUTOFMEMORY;
989 return S_OK;
992 static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
994 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
995 WS_XML_ATTRIBUTE *attr;
996 WS_XML_UTF8_TEXT *text;
997 unsigned int len = 0, ch, skip, quote;
998 const unsigned char *start;
999 WS_XML_STRING *prefix, *localname;
1000 HRESULT hr = WS_E_INVALID_FORMAT;
1002 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1004 start = read_current_ptr( reader );
1005 for (;;)
1007 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1008 if (!read_isnamechar( ch )) break;
1009 read_skip( reader, skip );
1010 len += skip;
1012 if (!len) goto error;
1014 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) goto error;
1015 hr = E_OUTOFMEMORY;
1016 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1018 heap_free( prefix );
1019 attr->isXmlNs = 1;
1020 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1022 heap_free( localname );
1023 goto error;
1025 attr->localName = localname;
1027 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1029 attr->isXmlNs = 1;
1030 attr->prefix = prefix;
1031 attr->localName = localname;
1033 else
1035 attr->prefix = prefix;
1036 attr->localName = localname;
1039 hr = WS_E_INVALID_FORMAT;
1040 read_skip_whitespace( reader );
1041 if (read_cmp( reader, "=", 1 )) goto error;
1042 read_skip( reader, 1 );
1044 read_skip_whitespace( reader );
1045 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) goto error;
1046 quote = read_utf8_char( reader, &skip );
1047 read_skip( reader, 1 );
1049 len = 0;
1050 start = read_current_ptr( reader );
1051 for (;;)
1053 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1054 if (ch == quote) break;
1055 read_skip( reader, skip );
1056 len += skip;
1058 read_skip( reader, 1 );
1060 hr = E_OUTOFMEMORY;
1061 if (attr->isXmlNs)
1063 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1064 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1065 if (!(text = alloc_utf8_text( NULL, 0 ))) goto error;
1067 else if (!(text = alloc_utf8_text( start, len ))) goto error;
1069 attr->value = &text->text;
1070 attr->singleQuote = (quote == '\'');
1072 *ret = attr;
1073 return S_OK;
1075 error:
1076 free_attribute( attr );
1077 return hr;
1080 static inline BOOL is_valid_parent( const struct node *node )
1082 if (!node) return FALSE;
1083 return node_type( node ) == WS_XML_NODE_TYPE_ELEMENT || node_type( node ) == WS_XML_NODE_TYPE_BOF;
1086 static struct node *read_find_parent( struct reader *reader )
1088 struct node *node = reader->current;
1089 if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT)
1091 if (!node->parent || !is_valid_parent( node->parent->parent )) return NULL;
1092 return node->parent->parent;
1094 else if (is_valid_parent( node )) return node;
1095 else if (is_valid_parent( node->parent )) return node->parent;
1096 return NULL;
1099 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1101 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1102 const WS_XML_STRING *ns;
1103 ULONG i;
1105 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1106 if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1107 if (!elem->ns->length) elem->ns->bytes = (BYTE *)(elem->ns + 1); /* quirk */
1109 for (i = 0; i < elem->attributeCount; i++)
1111 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1112 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1113 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1114 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1116 return S_OK;
1119 static HRESULT read_element( struct reader *reader )
1121 unsigned int len = 0, ch, skip;
1122 const unsigned char *start;
1123 struct node *node = NULL, *parent;
1124 WS_XML_ELEMENT_NODE *elem;
1125 WS_XML_ATTRIBUTE *attr = NULL;
1126 HRESULT hr = WS_E_INVALID_FORMAT;
1128 if (read_end_of_data( reader ))
1130 struct list *eof = list_tail( &reader->root->children );
1131 reader->current = LIST_ENTRY( eof, struct node, entry );
1132 reader->state = READER_STATE_EOF;
1133 return S_OK;
1136 if (read_cmp( reader, "<", 1 )) goto error;
1137 read_skip( reader, 1 );
1138 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1140 read_rewind( reader, 1 );
1141 goto error;
1144 start = read_current_ptr( reader );
1145 for (;;)
1147 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1148 if (!read_isnamechar( ch )) break;
1149 read_skip( reader, skip );
1150 len += skip;
1152 if (!len) goto error;
1154 if (!(parent = read_find_parent( reader ))) goto error;
1156 hr = E_OUTOFMEMORY;
1157 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error;
1158 elem = (WS_XML_ELEMENT_NODE *)node;
1159 if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1161 reader->current_attr = 0;
1162 for (;;)
1164 read_skip_whitespace( reader );
1165 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1166 if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
1167 if ((hr = append_attribute( elem, attr )) != S_OK)
1169 free_attribute( attr );
1170 goto error;
1172 reader->current_attr++;
1174 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1176 read_insert_node( reader, parent, node );
1177 reader->state = READER_STATE_STARTELEMENT;
1178 return S_OK;
1180 error:
1181 free_node( node );
1182 return hr;
1185 static HRESULT read_text( struct reader *reader )
1187 unsigned int len = 0, ch, skip;
1188 const unsigned char *start;
1189 struct node *node, *parent;
1190 WS_XML_TEXT_NODE *text;
1191 WS_XML_UTF8_TEXT *utf8;
1193 start = read_current_ptr( reader );
1194 for (;;)
1196 if (read_end_of_data( reader )) break;
1197 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1198 if (ch == '<') break;
1199 read_skip( reader, skip );
1200 len += skip;
1203 if (!(parent = read_find_parent( reader ))) return WS_E_INVALID_FORMAT;
1205 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1206 text = (WS_XML_TEXT_NODE *)node;
1207 if (!(utf8 = alloc_utf8_text( start, len )))
1209 heap_free( node );
1210 return E_OUTOFMEMORY;
1212 text->text = &utf8->text;
1214 read_insert_node( reader, parent, node );
1215 reader->state = READER_STATE_TEXT;
1216 return S_OK;
1219 static HRESULT read_node( struct reader * );
1221 static HRESULT read_startelement( struct reader *reader )
1223 struct node *node;
1225 read_skip_whitespace( reader );
1226 if (!read_cmp( reader, "/>", 2 ))
1228 read_skip( reader, 2 );
1229 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1230 read_insert_node( reader, reader->current, node );
1231 reader->state = READER_STATE_ENDELEMENT;
1232 return S_OK;
1234 else if (!read_cmp( reader, ">", 1 ))
1236 read_skip( reader, 1 );
1237 return read_node( reader );
1239 return WS_E_INVALID_FORMAT;
1242 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
1244 HRESULT hr;
1246 switch (reader->state)
1248 case READER_STATE_INITIAL:
1249 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
1250 break;
1252 case READER_STATE_STARTELEMENT:
1253 if (found) *found = TRUE;
1254 return S_OK;
1256 default:
1257 break;
1260 read_skip_whitespace( reader );
1261 if ((hr = read_element( reader )) == S_OK && found)
1263 if (reader->state == READER_STATE_STARTELEMENT)
1264 *found = TRUE;
1265 else
1266 *found = FALSE;
1269 return hr;
1272 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
1274 ULONG i;
1275 if (len1 != len2) return 1;
1276 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
1277 return 0;
1280 static struct node *read_find_start_element( struct reader *reader, const WS_XML_STRING *prefix,
1281 const WS_XML_STRING *localname )
1283 struct node *parent;
1284 const WS_XML_STRING *str;
1286 for (parent = reader->current; parent; parent = parent->parent)
1288 if (node_type( parent ) == WS_XML_NODE_TYPE_BOF) return NULL;
1289 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
1291 str = parent->hdr.prefix;
1292 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
1293 str = parent->hdr.localName;
1294 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
1295 return parent;
1299 return NULL;
1302 static HRESULT read_endelement( struct reader *reader )
1304 struct node *node, *parent;
1305 unsigned int len = 0, ch, skip;
1306 const unsigned char *start;
1307 WS_XML_STRING *prefix, *localname;
1308 HRESULT hr;
1310 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
1312 if (read_end_of_data( reader ))
1314 struct list *eof = list_tail( &reader->root->children );
1315 reader->current = LIST_ENTRY( eof, struct node, entry );
1316 reader->state = READER_STATE_EOF;
1317 return S_OK;
1320 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
1321 read_skip( reader, 2 );
1323 start = read_current_ptr( reader );
1324 for (;;)
1326 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1327 if (ch == '>')
1329 read_skip( reader, 1 );
1330 break;
1332 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
1333 read_skip( reader, skip );
1334 len += skip;
1337 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
1338 parent = read_find_start_element( reader, prefix, localname );
1339 heap_free( prefix );
1340 heap_free( localname );
1341 if (!parent) return WS_E_INVALID_FORMAT;
1343 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1344 read_insert_node( reader, parent, node );
1345 reader->state = READER_STATE_ENDELEMENT;
1346 return S_OK;
1349 static HRESULT read_comment( struct reader *reader )
1351 unsigned int len = 0, ch, skip;
1352 const unsigned char *start;
1353 struct node *node, *parent;
1354 WS_XML_COMMENT_NODE *comment;
1356 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
1357 read_skip( reader, 4 );
1359 start = read_current_ptr( reader );
1360 for (;;)
1362 if (!read_cmp( reader, "-->", 3 ))
1364 read_skip( reader, 3 );
1365 break;
1367 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1368 read_skip( reader, skip );
1369 len += skip;
1372 if (!(parent = read_find_parent( reader ))) return WS_E_INVALID_FORMAT;
1374 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
1375 comment = (WS_XML_COMMENT_NODE *)node;
1376 if (!(comment->value.bytes = heap_alloc( len )))
1378 heap_free( node );
1379 return E_OUTOFMEMORY;
1381 memcpy( comment->value.bytes, start, len );
1382 comment->value.length = len;
1384 read_insert_node( reader, parent, node );
1385 reader->state = READER_STATE_COMMENT;
1386 return S_OK;
1389 static HRESULT read_startcdata( struct reader *reader )
1391 struct node *node, *parent;
1393 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
1394 read_skip( reader, 9 );
1396 if (!(parent = read_find_parent( reader ))) return WS_E_INVALID_FORMAT;
1398 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
1399 read_insert_node( reader, parent, node );
1400 reader->state = READER_STATE_STARTCDATA;
1401 return S_OK;
1404 static HRESULT read_cdata( struct reader *reader )
1406 unsigned int len = 0, ch, skip;
1407 const unsigned char *start;
1408 struct node *node;
1409 WS_XML_TEXT_NODE *text;
1410 WS_XML_UTF8_TEXT *utf8;
1412 start = read_current_ptr( reader );
1413 for (;;)
1415 if (!read_cmp( reader, "]]>", 3 )) break;
1416 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1417 read_skip( reader, skip );
1418 len += skip;
1421 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1422 text = (WS_XML_TEXT_NODE *)node;
1423 if (!(utf8 = alloc_utf8_text( start, len )))
1425 heap_free( node );
1426 return E_OUTOFMEMORY;
1428 text->text = &utf8->text;
1430 read_insert_node( reader, reader->current, node );
1431 reader->state = READER_STATE_CDATA;
1432 return S_OK;
1435 static HRESULT read_endcdata( struct reader *reader )
1437 struct node *node;
1439 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
1440 read_skip( reader, 3 );
1442 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_CDATA ))) return E_OUTOFMEMORY;
1443 read_insert_node( reader, reader->current->parent, node );
1444 reader->state = READER_STATE_ENDCDATA;
1445 return S_OK;
1448 static HRESULT read_node( struct reader *reader )
1450 HRESULT hr;
1452 for (;;)
1454 if (read_end_of_data( reader ))
1456 struct list *eof = list_tail( &reader->root->children );
1457 reader->current = LIST_ENTRY( eof, struct node, entry );
1458 reader->state = READER_STATE_EOF;
1459 return S_OK;
1461 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
1462 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
1463 else if (!read_cmp( reader, "<?", 2 ))
1465 hr = read_xmldecl( reader );
1466 if (FAILED( hr )) return hr;
1468 else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
1469 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
1470 else if (!read_cmp( reader, "<!--", 4 )) return read_comment( reader );
1471 else if (!read_cmp( reader, "<", 1 )) return read_element( reader );
1472 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement( reader );
1473 else return read_text( reader );
1477 /**************************************************************************
1478 * WsReadEndElement [webservices.@]
1480 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
1482 struct reader *reader = (struct reader *)handle;
1484 TRACE( "%p %p\n", handle, error );
1485 if (error) FIXME( "ignoring error parameter\n" );
1487 if (!reader) return E_INVALIDARG;
1488 return read_endelement( reader );
1491 /**************************************************************************
1492 * WsReadNode [webservices.@]
1494 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
1496 struct reader *reader = (struct reader *)handle;
1498 TRACE( "%p %p\n", handle, error );
1499 if (error) FIXME( "ignoring error parameter\n" );
1501 if (!reader) return E_INVALIDARG;
1502 return read_node( reader );
1505 /**************************************************************************
1506 * WsReadStartElement [webservices.@]
1508 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
1510 struct reader *reader = (struct reader *)handle;
1512 TRACE( "%p %p\n", handle, error );
1513 if (error) FIXME( "ignoring error parameter\n" );
1515 if (!reader) return E_INVALIDARG;
1516 return read_startelement( reader );
1519 /**************************************************************************
1520 * WsReadToStartElement [webservices.@]
1522 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
1523 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
1525 struct reader *reader = (struct reader *)handle;
1527 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
1528 if (error) FIXME( "ignoring error parameter\n" );
1530 if (!reader) return E_INVALIDARG;
1531 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
1533 return read_to_startelement( reader, found );
1536 static BOOL move_to_root_element( struct reader *reader )
1538 struct list *ptr;
1539 struct node *node;
1541 if (!(ptr = list_head( &reader->root->children ))) return FALSE;
1542 node = LIST_ENTRY( ptr, struct node, entry );
1543 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1545 reader->current = node;
1546 return TRUE;
1548 while ((ptr = list_next( &reader->root->children, &node->entry )))
1550 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1551 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1553 reader->current = next;
1554 return TRUE;
1556 node = next;
1558 return FALSE;
1561 static BOOL move_to_next_element( struct reader *reader )
1563 struct list *ptr;
1564 struct node *node = reader->current;
1566 while ((ptr = list_next( &node->parent->children, &node->entry )))
1568 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1569 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1571 reader->current = next;
1572 return TRUE;
1574 node = next;
1576 return FALSE;
1579 static BOOL move_to_prev_element( struct reader *reader )
1581 struct list *ptr;
1582 struct node *node = reader->current;
1584 while ((ptr = list_prev( &node->parent->children, &node->entry )))
1586 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
1587 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
1589 reader->current = prev;
1590 return TRUE;
1592 node = prev;
1594 return FALSE;
1597 static BOOL move_to_child_element( struct reader *reader )
1599 struct list *ptr;
1600 struct node *node;
1602 if (!(ptr = list_head( &reader->current->children ))) return FALSE;
1603 node = LIST_ENTRY( ptr, struct node, entry );
1604 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1606 reader->current = node;
1607 return TRUE;
1609 while ((ptr = list_next( &reader->current->children, &node->entry )))
1611 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1612 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1614 reader->current = next;
1615 return TRUE;
1617 node = next;
1619 return FALSE;
1622 static BOOL move_to_end_element( struct reader *reader )
1624 struct list *ptr;
1625 struct node *node = reader->current;
1627 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
1629 if ((ptr = list_tail( &node->children )))
1631 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
1632 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
1634 reader->current = tail;
1635 return TRUE;
1638 return FALSE;
1641 static BOOL move_to_parent_element( struct reader *reader )
1643 struct node *parent = reader->current->parent;
1645 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
1646 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
1648 reader->current = parent;
1649 return TRUE;
1651 return FALSE;
1654 static BOOL move_to_first_node( struct reader *reader )
1656 struct list *ptr;
1657 if ((ptr = list_head( &reader->current->parent->children )))
1659 reader->current = LIST_ENTRY( ptr, struct node, entry );
1660 return TRUE;
1662 return FALSE;
1665 static BOOL move_to_next_node( struct reader *reader )
1667 struct list *ptr;
1668 if ((ptr = list_next( &reader->current->parent->children, &reader->current->entry )))
1670 reader->current = LIST_ENTRY( ptr, struct node, entry );
1671 return TRUE;
1673 return FALSE;
1676 static BOOL move_to_prev_node( struct reader *reader )
1678 struct list *ptr;
1679 if ((ptr = list_prev( &reader->current->parent->children, &reader->current->entry )))
1681 reader->current = LIST_ENTRY( ptr, struct node, entry );
1682 return TRUE;
1684 return FALSE;
1687 static BOOL move_to_child_node( struct reader *reader )
1689 struct list *ptr;
1690 if ((ptr = list_head( &reader->current->children )))
1692 reader->current = LIST_ENTRY( ptr, struct node, entry );
1693 return TRUE;
1695 return FALSE;
1698 static BOOL move_to_parent_node( struct reader *reader )
1700 struct node *parent = reader->current->parent;
1701 if (!parent) return FALSE;
1702 reader->current = parent;
1703 return TRUE;
1706 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
1708 struct list *ptr;
1709 BOOL success = FALSE;
1710 HRESULT hr = S_OK;
1712 if (!read_end_of_data( reader ))
1714 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
1715 if (hr != S_OK) return hr;
1717 switch (move)
1719 case WS_MOVE_TO_ROOT_ELEMENT:
1720 success = move_to_root_element( reader );
1721 break;
1723 case WS_MOVE_TO_NEXT_ELEMENT:
1724 success = move_to_next_element( reader );
1725 break;
1727 case WS_MOVE_TO_PREVIOUS_ELEMENT:
1728 success = move_to_prev_element( reader );
1729 break;
1731 case WS_MOVE_TO_CHILD_ELEMENT:
1732 success = move_to_child_element( reader );
1733 break;
1735 case WS_MOVE_TO_END_ELEMENT:
1736 success = move_to_end_element( reader );
1737 break;
1739 case WS_MOVE_TO_PARENT_ELEMENT:
1740 success = move_to_parent_element( reader );
1741 break;
1743 case WS_MOVE_TO_FIRST_NODE:
1744 success = move_to_first_node( reader );
1745 break;
1747 case WS_MOVE_TO_NEXT_NODE:
1748 success = move_to_next_node( reader );
1749 break;
1751 case WS_MOVE_TO_PREVIOUS_NODE:
1752 success = move_to_prev_node( reader );
1753 break;
1755 case WS_MOVE_TO_CHILD_NODE:
1756 success = move_to_child_node( reader );
1757 break;
1759 case WS_MOVE_TO_BOF:
1760 reader->current = reader->root;
1761 success = TRUE;
1762 break;
1764 case WS_MOVE_TO_EOF:
1765 if ((ptr = list_tail( &reader->root->children )))
1767 reader->current = LIST_ENTRY( ptr, struct node, entry );
1768 success = TRUE;
1770 break;
1772 default:
1773 FIXME( "unhandled move %u\n", move );
1774 return E_NOTIMPL;
1777 if (found)
1779 *found = success;
1780 return S_OK;
1782 return success ? S_OK : WS_E_INVALID_FORMAT;
1785 /**************************************************************************
1786 * WsMoveReader [webservices.@]
1788 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
1790 struct reader *reader = (struct reader *)handle;
1792 TRACE( "%p %u %p %p\n", handle, move, found, error );
1793 if (error) FIXME( "ignoring error parameter\n" );
1795 if (!reader) return E_INVALIDARG;
1796 if (!reader->input_type) return WS_E_INVALID_OPERATION;
1798 return read_move_to( reader, move, found );
1801 /**************************************************************************
1802 * WsReadStartAttribute [webservices.@]
1804 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
1806 struct reader *reader = (struct reader *)handle;
1807 WS_XML_ELEMENT_NODE *elem;
1809 TRACE( "%p %u %p\n", handle, index, error );
1810 if (error) FIXME( "ignoring error parameter\n" );
1812 if (!reader) return E_INVALIDARG;
1814 elem = &reader->current->hdr;
1815 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
1816 return WS_E_INVALID_FORMAT;
1818 reader->current_attr = index;
1819 reader->state = READER_STATE_STARTATTRIBUTE;
1820 return S_OK;
1823 /**************************************************************************
1824 * WsReadEndAttribute [webservices.@]
1826 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
1828 struct reader *reader = (struct reader *)handle;
1830 TRACE( "%p %p\n", handle, error );
1831 if (error) FIXME( "ignoring error parameter\n" );
1833 if (!reader) return E_INVALIDARG;
1835 if (reader->state != READER_STATE_STARTATTRIBUTE)
1836 return WS_E_INVALID_FORMAT;
1838 reader->state = READER_STATE_STARTELEMENT;
1839 return S_OK;
1842 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
1844 WCHAR *ret;
1846 switch (text->textType)
1848 case WS_XML_TEXT_TYPE_UTF8:
1850 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
1851 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
1852 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
1853 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
1854 ret[len] = 0;
1855 break;
1857 default:
1858 FIXME( "unhandled type %u\n", text->textType );
1859 return NULL;
1862 return ret;
1865 #define MAX_INT8 0x7f
1866 #define MIN_INT8 (-MAX_INT8 - 1)
1867 #define MAX_INT16 0x7fff
1868 #define MIN_INT16 (-MAX_INT16 - 1)
1869 #define MAX_INT32 0x7fffffff
1870 #define MIN_INT32 (-MAX_INT32 - 1)
1871 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1872 #define MIN_INT64 (-MAX_INT64 - 1)
1873 #define MAX_UINT8 0xff
1874 #define MAX_UINT16 0xffff
1875 #define MAX_UINT32 0xffffffff
1876 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1878 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
1880 BOOL negative = FALSE;
1881 const unsigned char *ptr = str;
1883 *ret = 0;
1884 while (len && read_isspace( *ptr )) { ptr++; len--; }
1885 while (len && read_isspace( ptr[len - 1] )) { len--; }
1886 if (!len) return WS_E_INVALID_FORMAT;
1888 if (*ptr == '-')
1890 negative = TRUE;
1891 ptr++;
1892 len--;
1894 if (!len) return WS_E_INVALID_FORMAT;
1896 while (len--)
1898 int val;
1900 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1901 val = *ptr - '0';
1902 if (negative) val = -val;
1904 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
1905 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
1907 return WS_E_NUMERIC_OVERFLOW;
1909 *ret = *ret * 10 + val;
1910 ptr++;
1913 return S_OK;
1916 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
1918 const unsigned char *ptr = str;
1920 *ret = 0;
1921 while (len && read_isspace( *ptr )) { ptr++; len--; }
1922 while (len && read_isspace( ptr[len - 1] )) { len--; }
1923 if (!len) return WS_E_INVALID_FORMAT;
1925 while (len--)
1927 unsigned int val;
1929 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1930 val = *ptr - '0';
1932 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
1933 *ret = *ret * 10 + val;
1934 ptr++;
1937 return S_OK;
1940 #if defined(__i386__) || defined(__x86_64__)
1942 #define RC_DOWN 0x100;
1943 static BOOL set_fp_rounding( unsigned short *save )
1945 #ifdef __GNUC__
1946 unsigned short fpword;
1948 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
1949 *save = fpword;
1950 fpword |= RC_DOWN;
1951 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
1952 return TRUE;
1953 #else
1954 FIXME( "not implemented\n" );
1955 return FALSE;
1956 #endif
1958 static void restore_fp_rounding( unsigned short fpword )
1960 #ifdef __GNUC__
1961 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
1962 #else
1963 FIXME( "not implemented\n" );
1964 #endif
1966 #else
1967 static BOOL set_fp_rounding( unsigned short *save )
1969 FIXME( "not implemented\n" );
1970 return FALSE;
1972 static void restore_fp_rounding( unsigned short fpword )
1974 FIXME( "not implemented\n" );
1976 #endif
1978 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
1980 static const unsigned __int64 nan = 0xfff8000000000000;
1981 static const unsigned __int64 inf = 0x7ff0000000000000;
1982 static const unsigned __int64 inf_min = 0xfff0000000000000;
1983 HRESULT hr = WS_E_INVALID_FORMAT;
1984 const unsigned char *p = str, *q;
1985 int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
1986 unsigned __int64 val = 0, tmp;
1987 long double exp_val = 1.0, exp_mul = 10.0;
1988 unsigned short fpword;
1990 while (len && read_isspace( *p )) { p++; len--; }
1991 while (len && read_isspace( p[len - 1] )) { len--; }
1992 if (!len) return WS_E_INVALID_FORMAT;
1994 if (len == 3 && !memcmp( p, "NaN", 3 ))
1996 *(unsigned __int64 *)ret = nan;
1997 return S_OK;
1999 else if (len == 3 && !memcmp( p, "INF", 3 ))
2001 *(unsigned __int64 *)ret = inf;
2002 return S_OK;
2004 else if (len == 4 && !memcmp( p, "-INF", 4 ))
2006 *(unsigned __int64 *)ret = inf_min;
2007 return S_OK;
2010 *ret = 0.0;
2011 if (*p == '-')
2013 sign = -1;
2014 p++; len--;
2016 else if (*p == '+') { p++; len--; };
2017 if (!len) return S_OK;
2019 if (!set_fp_rounding( &fpword )) return E_NOTIMPL;
2021 q = p;
2022 while (len && isdigit( *q )) { q++; len--; }
2023 have_digits = nb_digits = q - p;
2024 for (i = 0; i < nb_digits; i++)
2026 tmp = val * 10 + p[i] - '0';
2027 if (val > MAX_UINT64 / 10 || tmp < val)
2029 for (; i < nb_digits; i++) exp++;
2030 break;
2032 val = tmp;
2035 if (len)
2037 if (*q == '.')
2039 p = ++q; len--;
2040 while (len && isdigit( *q )) { q++; len--; };
2041 have_digits |= nb_digits = q - p;
2042 for (i = 0; i < nb_digits; i++)
2044 tmp = val * 10 + p[i] - '0';
2045 if (val > MAX_UINT64 / 10 || tmp < val) break;
2046 val = tmp;
2047 exp--;
2050 if (len > 1 && tolower(*q) == 'e')
2052 if (!have_digits) goto done;
2053 p = ++q; len--;
2054 if (*p == '-')
2056 exp_sign = -1;
2057 p++; len--;
2059 else if (*p == '+') { p++; len--; };
2061 q = p;
2062 while (len && isdigit( *q )) { q++; len--; };
2063 nb_digits = q - p;
2064 if (!nb_digits || len) goto done;
2065 for (i = 0; i < nb_digits; i++)
2067 if (exp_tmp > MAX_INT32 / 10 || (exp_tmp = exp_tmp * 10 + p[i] - '0') < 0)
2068 exp_tmp = MAX_INT32;
2070 exp_tmp *= exp_sign;
2072 if (exp < 0 && exp_tmp < 0 && exp + exp_tmp >= 0) exp = MIN_INT32;
2073 else if (exp > 0 && exp_tmp > 0 && exp + exp_tmp < 0) exp = MAX_INT32;
2074 else exp += exp_tmp;
2077 if (!have_digits || len) goto done;
2079 if ((neg_exp = exp < 0)) exp = -exp;
2080 for (; exp; exp >>= 1)
2082 if (exp & 1) exp_val *= exp_mul;
2083 exp_mul *= exp_mul;
2086 *ret = sign * (neg_exp ? val / exp_val : val * exp_val);
2087 hr = S_OK;
2089 done:
2090 restore_fp_rounding( fpword );
2091 return hr;
2094 #define TICKS_PER_SEC 10000000
2095 #define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
2096 #define TICKS_PER_HOUR (3600 * (ULONGLONG)TICKS_PER_SEC)
2097 #define TICKS_PER_DAY (86400 * (ULONGLONG)TICKS_PER_SEC)
2098 #define TICKS_MAX 3155378975999999999
2100 static const int month_offsets[2][12] =
2102 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
2103 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
2106 static const int month_days[2][12] =
2108 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
2109 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
2112 static inline int is_leap_year( int year )
2114 return !(year % 4) && (year % 100 || !(year % 400));
2117 static inline int valid_day( int year, int month, int day )
2119 return day > 0 && day <= month_days[is_leap_year( year )][month - 1];
2122 static inline int leap_days_before( int year )
2124 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
2127 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
2129 const unsigned char *p = bytes, *q;
2130 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
2132 while (len && read_isspace( *p )) { p++; len--; }
2133 while (len && read_isspace( p[len - 1] )) { len--; }
2135 q = p;
2136 while (len && isdigit( *q )) { q++; len--; };
2137 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
2138 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
2139 if (year < 1) return WS_E_INVALID_FORMAT;
2141 p = ++q; len--;
2142 while (len && isdigit( *q )) { q++; len--; };
2143 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
2144 month = (p[0] - '0') * 10 + p[1] - '0';
2145 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
2147 p = ++q; len--;
2148 while (len && isdigit( *q )) { q++; len--; };
2149 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
2150 day = (p[0] - '0') * 10 + p[1] - '0';
2151 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
2153 p = ++q; len--;
2154 while (len && isdigit( *q )) { q++; len--; };
2155 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2156 hour = (p[0] - '0') * 10 + p[1] - '0';
2157 if (hour > 24) return WS_E_INVALID_FORMAT;
2159 p = ++q; len--;
2160 while (len && isdigit( *q )) { q++; len--; };
2161 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2162 min = (p[0] - '0') * 10 + p[1] - '0';
2163 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
2165 p = ++q; len--;
2166 while (len && isdigit( *q )) { q++; len--; };
2167 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
2168 sec = (p[0] - '0') * 10 + p[1] - '0';
2169 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
2171 if (*q == '.')
2173 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
2174 p = ++q; len--;
2175 while (len && isdigit( *q )) { q++; len--; };
2176 nb_digits = q - p;
2177 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
2178 for (i = 0; i < nb_digits; i++)
2180 sec_frac += (p[i] - '0') * mul;
2181 mul /= 10;
2184 if (*q == 'Z')
2186 if (--len) return WS_E_INVALID_FORMAT;
2187 tz_hour = tz_min = tz_neg = 0;
2188 ret->format = WS_DATETIME_FORMAT_UTC;
2190 else if (*q == '+' || *q == '-')
2192 tz_neg = (*q == '-') ? 1 : 0;
2194 p = ++q; len--;
2195 while (len && isdigit( *q )) { q++; len--; };
2196 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2197 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
2198 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
2200 p = ++q; len--;
2201 while (len && isdigit( *q )) { q++; len--; };
2202 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
2203 tz_min = (p[0] - '0') * 10 + p[1] - '0';
2204 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
2206 ret->format = WS_DATETIME_FORMAT_LOCAL;
2208 else return WS_E_INVALID_FORMAT;
2210 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
2211 ret->ticks += month_offsets[is_leap_year( year )][month - 1] * TICKS_PER_DAY;
2212 ret->ticks += (day - 1) * TICKS_PER_DAY;
2213 ret->ticks += hour * TICKS_PER_HOUR;
2214 ret->ticks += min * TICKS_PER_MIN;
2215 ret->ticks += sec * TICKS_PER_SEC;
2216 ret->ticks += sec_frac;
2218 if (tz_neg)
2220 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
2221 return WS_E_INVALID_FORMAT;
2222 ret->ticks += tz_hour * TICKS_PER_HOUR;
2223 ret->ticks += tz_min * TICKS_PER_MIN;
2225 else
2227 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
2228 return WS_E_INVALID_FORMAT;
2229 ret->ticks -= tz_hour * TICKS_PER_HOUR;
2230 ret->ticks -= tz_min * TICKS_PER_MIN;
2233 return S_OK;
2236 #define TICKS_1601_01_01 504911232000000000
2238 /**************************************************************************
2239 * WsDateTimeToFileTime [webservices.@]
2241 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
2243 unsigned __int64 ticks;
2245 TRACE( "%p %p %p\n", dt, ft, error );
2246 if (error) FIXME( "ignoring error parameter\n" );
2248 if (!dt || !ft) return E_INVALIDARG;
2250 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
2251 ticks = dt->ticks - TICKS_1601_01_01;
2252 ft->dwHighDateTime = ticks >> 32;
2253 ft->dwLowDateTime = (DWORD)ticks;
2254 return S_OK;
2257 /**************************************************************************
2258 * WsFileTimeToDateTime [webservices.@]
2260 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
2262 unsigned __int64 ticks;
2264 TRACE( "%p %p %p\n", ft, dt, error );
2265 if (error) FIXME( "ignoring error parameter\n" );
2267 if (!dt || !ft) return E_INVALIDARG;
2269 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
2270 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
2271 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
2272 dt->ticks = ticks + TICKS_1601_01_01;
2273 dt->format = WS_DATETIME_FORMAT_UTC;
2274 return S_OK;
2277 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
2279 WS_XML_TEXT_NODE *text;
2281 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
2282 return WS_E_INVALID_FORMAT;
2284 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
2285 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
2287 FIXME( "text type %u not supported\n", text->text->textType );
2288 return E_NOTIMPL;
2290 *ret = (WS_XML_UTF8_TEXT *)text->text;
2291 return S_OK;
2294 static HRESULT read_get_attribute_text( struct reader *reader, ULONG index, WS_XML_UTF8_TEXT **ret )
2296 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2297 WS_XML_ATTRIBUTE *attr;
2299 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
2300 return WS_E_INVALID_FORMAT;
2302 attr = elem->attributes[index];
2303 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
2305 FIXME( "text type %u not supported\n", attr->value->textType );
2306 return E_NOTIMPL;
2308 *ret = (WS_XML_UTF8_TEXT *)attr->value;
2309 return S_OK;
2312 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
2313 const WS_XML_STRING *ns, ULONG *index )
2315 ULONG i;
2316 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2318 if (!localname)
2320 *index = reader->current_attr;
2321 return TRUE;
2323 for (i = 0; i < elem->attributeCount; i++)
2325 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
2326 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
2328 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
2329 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
2331 *index = i;
2332 return TRUE;
2335 return FALSE;
2338 /**************************************************************************
2339 * WsFindAttribute [webservices.@]
2341 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
2342 const WS_XML_STRING *ns, BOOL required, ULONG *index,
2343 WS_ERROR *error )
2345 struct reader *reader = (struct reader *)handle;
2347 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
2348 required, index, error );
2349 if (error) FIXME( "ignoring error parameter\n" );
2351 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
2353 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
2354 return WS_E_INVALID_OPERATION;
2356 if (!find_attribute( reader, localname, ns, index ))
2358 if (required) return WS_E_INVALID_FORMAT;
2359 *index = ~0u;
2360 return S_FALSE;
2362 return S_OK;
2365 static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
2366 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2367 WS_XML_UTF8_TEXT **ret, BOOL *found )
2369 switch (mapping)
2371 case WS_ATTRIBUTE_TYPE_MAPPING:
2373 ULONG index;
2374 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
2375 return read_get_attribute_text( reader, index, ret );
2377 case WS_ELEMENT_TYPE_MAPPING:
2378 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2379 case WS_ANY_ELEMENT_TYPE_MAPPING:
2381 HRESULT hr;
2382 *found = TRUE;
2383 if (localname)
2385 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2387 if (WsXmlStringEquals( localname, elem->localName, NULL ) != S_OK ||
2388 WsXmlStringEquals( ns, elem->ns, NULL ) != S_OK)
2390 *found = FALSE;
2391 return S_OK;
2393 if ((hr = read_startelement( reader )) != S_OK) return hr;
2395 return read_get_node_text( reader, ret );
2397 default:
2398 FIXME( "mapping %u not supported\n", mapping );
2399 return E_NOTIMPL;
2403 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
2404 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2405 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
2406 WS_HEAP *heap, void *ret, ULONG size )
2408 WS_XML_UTF8_TEXT *utf8;
2409 HRESULT hr;
2410 BOOL found, val = FALSE;
2412 if (desc)
2414 FIXME( "description not supported\n" );
2415 return E_NOTIMPL;
2417 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2418 if (found)
2420 ULONG len = utf8->value.length;
2421 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
2422 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
2423 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
2424 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
2425 else return WS_E_INVALID_FORMAT;
2428 switch (option)
2430 case WS_READ_REQUIRED_VALUE:
2431 if (!found) return WS_E_INVALID_FORMAT;
2432 if (size != sizeof(BOOL)) return E_INVALIDARG;
2433 *(BOOL *)ret = val;
2434 break;
2436 case WS_READ_REQUIRED_POINTER:
2437 if (!found) return WS_E_INVALID_FORMAT;
2438 /* fall through */
2440 case WS_READ_OPTIONAL_POINTER:
2442 BOOL *heap_val = NULL;
2443 if (size != sizeof(heap_val)) return E_INVALIDARG;
2444 if (found)
2446 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2447 *heap_val = val;
2449 *(BOOL **)ret = heap_val;
2450 break;
2452 default:
2453 FIXME( "read option %u not supported\n", option );
2454 return E_NOTIMPL;
2457 return S_OK;
2460 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
2461 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2462 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
2463 WS_HEAP *heap, void *ret, ULONG size )
2465 WS_XML_UTF8_TEXT *utf8;
2466 HRESULT hr;
2467 INT64 val;
2468 BOOL found;
2470 if (desc)
2472 FIXME( "description not supported\n" );
2473 return E_NOTIMPL;
2475 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2476 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
2477 return hr;
2479 switch (option)
2481 case WS_READ_REQUIRED_VALUE:
2482 if (!found) return WS_E_INVALID_FORMAT;
2483 if (size != sizeof(INT8)) return E_INVALIDARG;
2484 *(INT8 *)ret = val;
2485 break;
2487 case WS_READ_REQUIRED_POINTER:
2488 if (!found) return WS_E_INVALID_FORMAT;
2489 /* fall through */
2491 case WS_READ_OPTIONAL_POINTER:
2493 INT8 *heap_val = NULL;
2494 if (size != sizeof(heap_val)) return E_INVALIDARG;
2495 if (found)
2497 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2498 *heap_val = val;
2500 *(INT8 **)ret = heap_val;
2501 break;
2503 default:
2504 FIXME( "read option %u not supported\n", option );
2505 return E_NOTIMPL;
2508 return S_OK;
2511 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
2512 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2513 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
2514 WS_HEAP *heap, void *ret, ULONG size )
2516 WS_XML_UTF8_TEXT *utf8;
2517 HRESULT hr;
2518 INT64 val;
2519 BOOL found;
2521 if (desc)
2523 FIXME( "description not supported\n" );
2524 return E_NOTIMPL;
2526 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2527 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
2528 return hr;
2530 switch (option)
2532 case WS_READ_REQUIRED_VALUE:
2533 if (!found) return WS_E_INVALID_FORMAT;
2534 if (size != sizeof(INT16)) return E_INVALIDARG;
2535 *(INT16 *)ret = val;
2536 break;
2538 case WS_READ_REQUIRED_POINTER:
2539 if (!found) return WS_E_INVALID_FORMAT;
2540 /* fall through */
2542 case WS_READ_OPTIONAL_POINTER:
2544 INT16 *heap_val = NULL;
2545 if (size != sizeof(heap_val)) return E_INVALIDARG;
2546 if (found)
2548 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2549 *heap_val = val;
2551 *(INT16 **)ret = heap_val;
2552 break;
2554 default:
2555 FIXME( "read option %u not supported\n", option );
2556 return E_NOTIMPL;
2559 return S_OK;
2562 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
2563 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2564 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
2565 WS_HEAP *heap, void *ret, ULONG size )
2567 WS_XML_UTF8_TEXT *utf8;
2568 HRESULT hr;
2569 INT64 val;
2570 BOOL found;
2572 if (desc)
2574 FIXME( "description not supported\n" );
2575 return E_NOTIMPL;
2577 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2578 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
2579 return hr;
2581 switch (option)
2583 case WS_READ_REQUIRED_VALUE:
2584 if (!found) return WS_E_INVALID_FORMAT;
2585 if (size != sizeof(INT32)) return E_INVALIDARG;
2586 *(INT32 *)ret = val;
2587 break;
2589 case WS_READ_REQUIRED_POINTER:
2590 if (!found) return WS_E_INVALID_FORMAT;
2591 /* fall through */
2593 case WS_READ_OPTIONAL_POINTER:
2595 INT32 *heap_val = NULL;
2596 if (size != sizeof(heap_val)) return E_INVALIDARG;
2597 if (found)
2599 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2600 *heap_val = val;
2602 *(INT32 **)ret = heap_val;
2603 break;
2605 default:
2606 FIXME( "read option %u not supported\n", option );
2607 return E_NOTIMPL;
2610 return S_OK;
2613 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
2614 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2615 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
2616 WS_HEAP *heap, void *ret, ULONG size )
2618 WS_XML_UTF8_TEXT *utf8;
2619 HRESULT hr;
2620 INT64 val;
2621 BOOL found;
2623 if (desc)
2625 FIXME( "description not supported\n" );
2626 return E_NOTIMPL;
2628 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2629 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
2630 return hr;
2632 switch (option)
2634 case WS_READ_REQUIRED_VALUE:
2635 if (!found) return WS_E_INVALID_FORMAT;
2636 if (size != sizeof(INT64)) return E_INVALIDARG;
2637 *(INT64 *)ret = val;
2638 break;
2640 case WS_READ_REQUIRED_POINTER:
2641 if (!found) return WS_E_INVALID_FORMAT;
2642 /* fall through */
2644 case WS_READ_OPTIONAL_POINTER:
2646 INT64 *heap_val = NULL;
2647 if (size != sizeof(heap_val)) return E_INVALIDARG;
2648 if (found)
2650 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2651 *heap_val = val;
2653 *(INT64 **)ret = heap_val;
2654 break;
2656 default:
2657 FIXME( "read option %u not supported\n", option );
2658 return E_NOTIMPL;
2661 return S_OK;
2664 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
2665 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2666 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
2667 WS_HEAP *heap, void *ret, ULONG size )
2669 WS_XML_UTF8_TEXT *utf8;
2670 HRESULT hr;
2671 UINT64 val;
2672 BOOL found;
2674 if (desc)
2676 FIXME( "description not supported\n" );
2677 return E_NOTIMPL;
2679 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2680 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
2681 return hr;
2683 switch (option)
2685 case WS_READ_REQUIRED_VALUE:
2686 if (!found) return WS_E_INVALID_FORMAT;
2687 if (size != sizeof(UINT8)) return E_INVALIDARG;
2688 *(UINT8 *)ret = val;
2689 break;
2691 case WS_READ_REQUIRED_POINTER:
2692 if (!found) return WS_E_INVALID_FORMAT;
2693 /* fall through */
2695 case WS_READ_OPTIONAL_POINTER:
2697 UINT8 *heap_val = NULL;
2698 if (size != sizeof(heap_val)) return E_INVALIDARG;
2699 if (found)
2701 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2702 *heap_val = val;
2704 *(UINT8 **)ret = heap_val;
2705 break;
2707 default:
2708 FIXME( "read option %u not supported\n", option );
2709 return E_NOTIMPL;
2712 return S_OK;
2715 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
2716 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2717 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
2718 WS_HEAP *heap, void *ret, ULONG size )
2720 WS_XML_UTF8_TEXT *utf8;
2721 HRESULT hr;
2722 UINT64 val;
2723 BOOL found;
2725 if (desc)
2727 FIXME( "description not supported\n" );
2728 return E_NOTIMPL;
2730 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2731 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
2732 return hr;
2734 switch (option)
2736 case WS_READ_REQUIRED_VALUE:
2737 if (!found) return WS_E_INVALID_FORMAT;
2738 if (size != sizeof(UINT16)) return E_INVALIDARG;
2739 *(UINT16 *)ret = val;
2740 break;
2742 case WS_READ_REQUIRED_POINTER:
2743 if (!found) return WS_E_INVALID_FORMAT;
2744 /* fall through */
2746 case WS_READ_OPTIONAL_POINTER:
2748 UINT16 *heap_val = NULL;
2749 if (size != sizeof(heap_val)) return E_INVALIDARG;
2750 if (found)
2752 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2753 *heap_val = val;
2755 *(UINT16 **)ret = heap_val;
2756 break;
2758 default:
2759 FIXME( "read option %u not supported\n", option );
2760 return E_NOTIMPL;
2763 return S_OK;
2766 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
2767 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2768 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
2769 WS_HEAP *heap, void *ret, ULONG size )
2771 WS_XML_UTF8_TEXT *utf8;
2772 HRESULT hr;
2773 UINT64 val;
2774 BOOL found;
2776 if (desc)
2778 FIXME( "description not supported\n" );
2779 return E_NOTIMPL;
2781 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2782 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
2783 return hr;
2785 switch (option)
2787 case WS_READ_REQUIRED_VALUE:
2788 if (!found) return WS_E_INVALID_FORMAT;
2789 if (size != sizeof(UINT32)) return E_INVALIDARG;
2790 *(UINT32 *)ret = val;
2791 break;
2793 case WS_READ_REQUIRED_POINTER:
2794 if (!found) return WS_E_INVALID_FORMAT;
2795 /* fall through */
2797 case WS_READ_OPTIONAL_POINTER:
2799 UINT32 *heap_val = NULL;
2800 if (size != sizeof(heap_val)) return E_INVALIDARG;
2801 if (found)
2803 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2804 *heap_val = val;
2806 *(UINT32 **)ret = heap_val;
2807 break;
2809 default:
2810 FIXME( "read option %u not supported\n", option );
2811 return E_NOTIMPL;
2814 return S_OK;
2817 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
2818 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2819 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
2820 WS_HEAP *heap, void *ret, ULONG size )
2822 WS_XML_UTF8_TEXT *utf8;
2823 HRESULT hr;
2824 UINT64 val;
2825 BOOL found;
2827 if (desc)
2829 FIXME( "description not supported\n" );
2830 return E_NOTIMPL;
2832 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2833 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
2834 return hr;
2836 switch (option)
2838 case WS_READ_REQUIRED_VALUE:
2839 if (!found) return WS_E_INVALID_FORMAT;
2840 if (size != sizeof(UINT64)) return E_INVALIDARG;
2841 *(UINT64 *)ret = val;
2842 break;
2844 case WS_READ_REQUIRED_POINTER:
2845 if (!found) return WS_E_INVALID_FORMAT;
2846 /* fall through */
2848 case WS_READ_OPTIONAL_POINTER:
2850 UINT64 *heap_val = NULL;
2851 if (size != sizeof(heap_val)) return E_INVALIDARG;
2852 if (found)
2854 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2855 *heap_val = val;
2857 *(UINT64 **)ret = heap_val;
2858 break;
2860 default:
2861 FIXME( "read option %u not supported\n", option );
2862 return E_NOTIMPL;
2865 return S_OK;
2868 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
2869 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2870 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
2871 WS_HEAP *heap, void *ret, ULONG size )
2873 WS_XML_UTF8_TEXT *utf8;
2874 HRESULT hr;
2875 double val = 0.0;
2876 BOOL found;
2878 if (desc) FIXME( "ignoring description\n" );
2880 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2881 if (found && (hr = str_to_double( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
2883 switch (option)
2885 case WS_READ_REQUIRED_VALUE:
2886 if (!found) return WS_E_INVALID_FORMAT;
2887 if (size != sizeof(double)) return E_INVALIDARG;
2888 *(double *)ret = val;
2889 break;
2891 case WS_READ_REQUIRED_POINTER:
2892 if (!found) return WS_E_INVALID_FORMAT;
2893 /* fall through */
2895 case WS_READ_OPTIONAL_POINTER:
2897 double *heap_val = NULL;
2898 if (size != sizeof(heap_val)) return E_INVALIDARG;
2899 if (found)
2901 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2902 *heap_val = val;
2904 *(double **)ret = heap_val;
2905 break;
2907 default:
2908 FIXME( "read option %u not supported\n", option );
2909 return E_NOTIMPL;
2912 return S_OK;
2915 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
2916 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2917 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
2918 WS_HEAP *heap, WCHAR **ret, ULONG size )
2920 WS_XML_UTF8_TEXT *utf8;
2921 HRESULT hr;
2922 WCHAR *str = NULL;
2923 BOOL found;
2925 if (desc)
2927 FIXME( "description not supported\n" );
2928 return E_NOTIMPL;
2930 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2931 if (found && !(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
2933 switch (option)
2935 case WS_READ_REQUIRED_POINTER:
2936 if (!found) return WS_E_INVALID_FORMAT;
2937 /* fall through */
2939 case WS_READ_OPTIONAL_POINTER:
2940 if (size != sizeof(str)) return E_INVALIDARG;
2941 *ret = str;
2942 break;
2944 default:
2945 FIXME( "read option %u not supported\n", option );
2946 return E_NOTIMPL;
2949 return S_OK;
2952 static HRESULT get_enum_value( const WS_XML_UTF8_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
2954 ULONG i;
2955 for (i = 0; i < desc->valueCount; i++)
2957 if (WsXmlStringEquals( &text->value, desc->values[i].name, NULL ) == S_OK)
2959 *ret = desc->values[i].value;
2960 return S_OK;
2963 return WS_E_INVALID_FORMAT;
2966 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
2967 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2968 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
2969 WS_HEAP *heap, void *ret, ULONG size )
2971 WS_XML_UTF8_TEXT *utf8;
2972 HRESULT hr;
2973 int val = 0;
2974 BOOL found;
2976 if (!desc) return E_INVALIDARG;
2978 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2979 if (found && (hr = get_enum_value( utf8, desc, &val )) != S_OK) return hr;
2981 switch (option)
2983 case WS_READ_REQUIRED_VALUE:
2984 if (!found) return WS_E_INVALID_FORMAT;
2985 if (size != sizeof(int)) return E_INVALIDARG;
2986 *(int *)ret = val;
2987 break;
2989 case WS_READ_REQUIRED_POINTER:
2990 if (!found) return WS_E_INVALID_FORMAT;
2991 /* fall through */
2993 case WS_READ_OPTIONAL_POINTER:
2995 int *heap_val = NULL;
2996 if (size != sizeof(heap_val)) return E_INVALIDARG;
2997 if (found)
2999 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3000 *heap_val = val;
3002 *(int **)ret = heap_val;
3003 break;
3005 default:
3006 FIXME( "read option %u not supported\n", option );
3007 return E_NOTIMPL;
3010 return S_OK;
3013 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
3014 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3015 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
3016 WS_HEAP *heap, void *ret, ULONG size )
3018 WS_XML_UTF8_TEXT *utf8;
3019 HRESULT hr;
3020 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
3021 BOOL found;
3023 if (desc) FIXME( "ignoring description\n" );
3025 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3026 if (found && (hr = str_to_datetime( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
3028 switch (option)
3030 case WS_READ_REQUIRED_VALUE:
3031 if (!found) return WS_E_INVALID_FORMAT;
3032 if (size != sizeof(WS_DATETIME)) return E_INVALIDARG;
3033 *(WS_DATETIME *)ret = val;
3034 break;
3036 case WS_READ_REQUIRED_POINTER:
3037 if (!found) return WS_E_INVALID_FORMAT;
3038 /* fall through */
3040 case WS_READ_OPTIONAL_POINTER:
3042 WS_DATETIME *heap_val = NULL;
3043 if (size != sizeof(heap_val)) return E_INVALIDARG;
3044 if (found)
3046 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3047 *heap_val = val;
3049 *(WS_DATETIME **)ret = heap_val;
3050 break;
3052 default:
3053 FIXME( "read option %u not supported\n", option );
3054 return E_NOTIMPL;
3057 return S_OK;
3060 static BOOL is_empty_text_node( const struct node *node )
3062 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
3063 const WS_XML_UTF8_TEXT *utf8;
3064 ULONG i;
3066 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
3067 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
3069 ERR( "unhandled text type %u\n", text->text->textType );
3070 return FALSE;
3072 utf8 = (const WS_XML_UTF8_TEXT *)text->text;
3073 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
3074 return TRUE;
3077 static HRESULT read_next_node( struct reader *reader )
3079 if (reader->current == reader->last) return read_node( reader );
3080 if (move_to_child_node( reader )) return S_OK;
3081 if (move_to_next_node( reader )) return S_OK;
3082 if (!move_to_parent_node( reader )) return WS_E_INVALID_FORMAT;
3083 if (move_to_next_node( reader )) return S_OK;
3084 return WS_E_INVALID_FORMAT;
3087 /* skips comment and empty text nodes */
3088 static HRESULT read_type_next_node( struct reader *reader )
3090 for (;;)
3092 HRESULT hr;
3093 WS_XML_NODE_TYPE type;
3095 if ((hr = read_next_node( reader )) != S_OK) return hr;
3096 type = node_type( reader->current );
3097 if (type == WS_XML_NODE_TYPE_COMMENT ||
3098 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
3099 return S_OK;
3103 static BOOL match_current_element( struct reader *reader, const WS_XML_STRING *localname,
3104 const WS_XML_STRING *ns )
3106 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3107 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3108 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
3109 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
3112 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
3113 const WS_XML_STRING *ns )
3115 struct node *node;
3116 ULONG attr;
3117 HRESULT hr;
3119 if (!localname) return S_OK; /* assume reader is already correctly positioned */
3120 if (reader->current == reader->last)
3122 BOOL found;
3123 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
3124 if (!found) return WS_E_INVALID_FORMAT;
3126 if (match_current_element( reader, localname, ns )) return S_OK;
3128 node = reader->current;
3129 attr = reader->current_attr;
3131 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
3132 if (match_current_element( reader, localname, ns )) return S_OK;
3134 reader->current = node;
3135 reader->current_attr = attr;
3137 return WS_E_INVALID_FORMAT;
3140 static ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
3142 switch (type)
3144 case WS_INT8_TYPE:
3145 case WS_UINT8_TYPE:
3146 return sizeof(INT8);
3148 case WS_INT16_TYPE:
3149 case WS_UINT16_TYPE:
3150 return sizeof(INT16);
3152 case WS_BOOL_TYPE:
3153 case WS_INT32_TYPE:
3154 case WS_UINT32_TYPE:
3155 case WS_ENUM_TYPE:
3156 return sizeof(INT32);
3158 case WS_INT64_TYPE:
3159 case WS_UINT64_TYPE:
3160 return sizeof(INT64);
3162 case WS_DOUBLE_TYPE:
3163 return sizeof(double);
3165 case WS_DATETIME_TYPE:
3166 return sizeof(WS_DATETIME);
3168 case WS_WSZ_TYPE:
3169 return sizeof(WCHAR *);
3171 case WS_STRUCT_TYPE:
3172 return desc->size;
3174 default:
3175 ERR( "unhandled type %u\n", type );
3176 return 0;
3180 static WS_READ_OPTION get_array_read_option( WS_TYPE type )
3182 switch (type)
3184 case WS_BOOL_TYPE:
3185 case WS_INT8_TYPE:
3186 case WS_INT16_TYPE:
3187 case WS_INT32_TYPE:
3188 case WS_INT64_TYPE:
3189 case WS_UINT8_TYPE:
3190 case WS_UINT16_TYPE:
3191 case WS_UINT32_TYPE:
3192 case WS_UINT64_TYPE:
3193 case WS_DOUBLE_TYPE:
3194 case WS_ENUM_TYPE:
3195 case WS_STRUCT_TYPE:
3196 case WS_DATETIME_TYPE:
3197 return WS_READ_REQUIRED_VALUE;
3199 case WS_WSZ_TYPE:
3200 return WS_READ_REQUIRED_POINTER;
3202 default:
3203 FIXME( "unhandled type %u\n", type );
3204 return 0;
3208 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
3209 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
3210 void *, ULONG );
3212 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3213 WS_HEAP *heap, void **ret, ULONG size, ULONG *count )
3215 HRESULT hr;
3216 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
3217 WS_READ_OPTION option;
3218 char *buf;
3220 if (size != sizeof(void *) || !(option = get_array_read_option( desc->type ))) return E_INVALIDARG;
3222 /* wrapper element */
3223 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
3224 return hr;
3226 if (option == WS_READ_REQUIRED_VALUE)
3227 item_size = get_type_size( desc->type, desc->typeDescription );
3228 else
3229 item_size = sizeof(void *);
3231 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
3232 for (;;)
3234 if (nb_items >= nb_allocated)
3236 if (!(buf = ws_realloc_zero( heap, buf, nb_allocated * 2 * item_size )))
3237 return WS_E_QUOTA_EXCEEDED;
3238 nb_allocated *= 2;
3240 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
3241 desc->typeDescription, option, heap, buf + offset, item_size );
3242 if (hr == WS_E_INVALID_FORMAT) break;
3243 if (hr != S_OK)
3245 ws_free( heap, buf );
3246 return hr;
3248 offset += item_size;
3249 nb_items++;
3252 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
3254 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
3256 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
3257 desc->itemRange->maxItemCount );
3258 ws_free( heap, buf );
3259 return WS_E_INVALID_FORMAT;
3262 *count = nb_items;
3263 *ret = buf;
3265 return S_OK;
3268 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3269 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
3271 HRESULT hr;
3272 if (reader->current == reader->last)
3274 BOOL found;
3275 if ((hr = read_to_startelement( reader, &found )) != S_OK) return S_OK;
3276 if (!found) return WS_E_INVALID_FORMAT;
3278 if ((hr = read_next_node( reader )) != S_OK) return hr;
3279 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
3281 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
3282 desc->typeDescription, option, heap, ret, size );
3285 static WS_READ_OPTION get_field_read_option( WS_TYPE type )
3287 switch (type)
3289 case WS_BOOL_TYPE:
3290 case WS_INT8_TYPE:
3291 case WS_INT16_TYPE:
3292 case WS_INT32_TYPE:
3293 case WS_INT64_TYPE:
3294 case WS_UINT8_TYPE:
3295 case WS_UINT16_TYPE:
3296 case WS_UINT32_TYPE:
3297 case WS_UINT64_TYPE:
3298 case WS_DOUBLE_TYPE:
3299 case WS_ENUM_TYPE:
3300 case WS_DATETIME_TYPE:
3301 return WS_READ_REQUIRED_VALUE;
3303 case WS_WSZ_TYPE:
3304 case WS_STRUCT_TYPE:
3305 return WS_READ_REQUIRED_POINTER;
3307 default:
3308 FIXME( "unhandled type %u\n", type );
3309 return 0;
3313 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3314 WS_HEAP *heap, char *buf )
3316 char *ptr;
3317 WS_READ_OPTION option;
3318 ULONG size;
3319 HRESULT hr;
3321 if (!desc) return E_INVALIDARG;
3322 if (desc->options & ~(WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
3324 FIXME( "options %08x not supported\n", desc->options );
3325 return E_NOTIMPL;
3327 if (!(option = get_field_read_option( desc->type ))) return E_INVALIDARG;
3329 if (option == WS_READ_REQUIRED_VALUE)
3330 size = get_type_size( desc->type, desc->typeDescription );
3331 else
3332 size = sizeof(void *);
3334 ptr = buf + desc->offset;
3335 switch (desc->mapping)
3337 case WS_ATTRIBUTE_FIELD_MAPPING:
3338 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
3339 desc->typeDescription, option, heap, ptr, size );
3340 break;
3342 case WS_ELEMENT_FIELD_MAPPING:
3343 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
3344 desc->typeDescription, option, heap, ptr, size );
3345 break;
3347 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
3349 ULONG count;
3350 hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, size, &count );
3351 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
3352 break;
3354 case WS_TEXT_FIELD_MAPPING:
3355 hr = read_type_text( reader, desc, option, heap, ptr, size );
3356 break;
3358 default:
3359 FIXME( "unhandled field mapping %u\n", desc->mapping );
3360 return E_NOTIMPL;
3363 if (hr == WS_E_INVALID_FORMAT && desc->options & WS_FIELD_OPTIONAL)
3365 switch (option)
3367 case WS_READ_REQUIRED_VALUE:
3368 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
3369 else memset( ptr, 0, size );
3370 return S_OK;
3372 case WS_READ_REQUIRED_POINTER:
3373 *(void **)ptr = NULL;
3374 return S_OK;
3376 default:
3377 ERR( "unhandled option %u\n", option );
3378 return E_NOTIMPL;
3382 return hr;
3385 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
3386 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3387 const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
3388 WS_HEAP *heap, void *ret, ULONG size )
3390 ULONG i;
3391 HRESULT hr;
3392 char *buf;
3394 if (!desc) return E_INVALIDARG;
3396 if (desc->structOptions)
3398 FIXME( "struct options %08x not supported\n", desc->structOptions );
3399 return E_NOTIMPL;
3402 switch (option)
3404 case WS_READ_REQUIRED_POINTER:
3405 case WS_READ_OPTIONAL_POINTER:
3406 if (size != sizeof(void *)) return E_INVALIDARG;
3407 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
3408 break;
3410 case WS_READ_REQUIRED_VALUE:
3411 if (size != desc->size) return E_INVALIDARG;
3412 buf = ret;
3413 break;
3415 default:
3416 FIXME( "unhandled read option %u\n", option );
3417 return E_NOTIMPL;
3420 for (i = 0; i < desc->fieldCount; i++)
3422 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
3423 break;
3426 switch (option)
3428 case WS_READ_REQUIRED_POINTER:
3429 if (hr != S_OK)
3431 ws_free( heap, buf );
3432 return hr;
3434 *(char **)ret = buf;
3435 return S_OK;
3437 case WS_READ_OPTIONAL_POINTER:
3438 if (hr != S_OK)
3440 ws_free( heap, buf );
3441 buf = NULL;
3443 *(char **)ret = buf;
3444 return S_OK;
3446 case WS_READ_REQUIRED_VALUE:
3447 return hr;
3449 default:
3450 ERR( "unhandled read option %u\n", option );
3451 return E_NOTIMPL;
3455 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
3456 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3457 const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
3458 void *value, ULONG size )
3460 HRESULT hr;
3462 switch (mapping)
3464 case WS_ELEMENT_TYPE_MAPPING:
3465 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
3466 if ((hr = read_type_next_element_node( reader, localname, ns )) != S_OK) return hr;
3467 break;
3469 case WS_ANY_ELEMENT_TYPE_MAPPING:
3470 case WS_ATTRIBUTE_TYPE_MAPPING:
3471 break;
3473 default:
3474 FIXME( "unhandled mapping %u\n", mapping );
3475 return E_NOTIMPL;
3478 switch (type)
3480 case WS_STRUCT_TYPE:
3481 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3482 return hr;
3483 break;
3485 case WS_BOOL_TYPE:
3486 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3487 return hr;
3488 break;
3490 case WS_INT8_TYPE:
3491 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3492 return hr;
3493 break;
3495 case WS_INT16_TYPE:
3496 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3497 return hr;
3498 break;
3500 case WS_INT32_TYPE:
3501 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3502 return hr;
3503 break;
3505 case WS_INT64_TYPE:
3506 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3507 return hr;
3508 break;
3510 case WS_UINT8_TYPE:
3511 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3512 return hr;
3513 break;
3515 case WS_UINT16_TYPE:
3516 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3517 return hr;
3518 break;
3520 case WS_UINT32_TYPE:
3521 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3522 return hr;
3523 break;
3525 case WS_UINT64_TYPE:
3526 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3527 return hr;
3528 break;
3530 case WS_DOUBLE_TYPE:
3531 if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3532 return hr;
3533 break;
3535 case WS_WSZ_TYPE:
3536 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3537 return hr;
3538 break;
3540 case WS_ENUM_TYPE:
3541 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3542 return hr;
3543 break;
3545 case WS_DATETIME_TYPE:
3546 if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3547 return hr;
3548 break;
3550 default:
3551 FIXME( "type %u not supported\n", type );
3552 return E_NOTIMPL;
3555 switch (mapping)
3557 case WS_ELEMENT_TYPE_MAPPING:
3558 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
3559 return read_type_next_node( reader );
3561 case WS_ATTRIBUTE_TYPE_MAPPING:
3562 default:
3563 return S_OK;
3567 /**************************************************************************
3568 * WsReadType [webservices.@]
3570 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
3571 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
3572 ULONG size, WS_ERROR *error )
3574 struct reader *reader = (struct reader *)handle;
3575 HRESULT hr;
3577 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
3578 size, error );
3579 if (error) FIXME( "ignoring error parameter\n" );
3581 if (!reader || !value) return E_INVALIDARG;
3583 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
3584 return hr;
3586 switch (mapping)
3588 case WS_ELEMENT_TYPE_MAPPING:
3589 if ((hr = read_node( reader )) != S_OK) return hr;
3590 break;
3592 default:
3593 break;
3596 if (!read_end_of_data( reader )) return WS_E_INVALID_FORMAT;
3597 return S_OK;
3600 /**************************************************************************
3601 * WsReadElement [webservices.@]
3603 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
3604 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
3605 WS_ERROR *error )
3607 struct reader *reader = (struct reader *)handle;
3609 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
3610 if (error) FIXME( "ignoring error parameter\n" );
3612 if (!reader || !desc || !value) return E_INVALIDARG;
3614 return read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
3615 desc->elementNs, desc->typeDescription, option, heap, value, size );
3618 /**************************************************************************
3619 * WsSetErrorProperty [webservices.@]
3621 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
3622 ULONG size )
3624 struct error *error = (struct error *)handle;
3626 TRACE( "%p %u %p %u\n", handle, id, value, size );
3628 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
3629 return prop_set( error->prop, error->prop_count, id, value, size );
3632 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
3634 static const char bom[] = {0xef,0xbb,0xbf};
3635 const unsigned char *p = data;
3637 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
3638 (size > 2 && !(*offset = 0));
3641 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
3643 static const char bom[] = {0xff,0xfe};
3644 const unsigned char *p = data;
3646 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
3647 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
3650 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
3652 WS_CHARSET ret = 0;
3654 /* FIXME: parse xml declaration */
3656 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
3657 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
3658 else
3660 FIXME( "charset not recognized\n" );
3661 return 0;
3664 TRACE( "detected charset %u\n", ret );
3665 return ret;
3668 static void set_input_buffer( struct reader *reader, const unsigned char *data, ULONG size )
3670 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
3671 reader->input_data = data;
3672 reader->input_size = size;
3674 reader->read_size = reader->input_size;
3675 reader->read_pos = 0;
3676 reader->read_bufptr = reader->input_data;
3679 /**************************************************************************
3680 * WsSetInput [webservices.@]
3682 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
3683 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
3684 ULONG count, WS_ERROR *error )
3686 struct reader *reader = (struct reader *)handle;
3687 struct node *node;
3688 HRESULT hr;
3689 ULONG i, offset = 0;
3691 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
3692 if (error) FIXME( "ignoring error parameter\n" );
3694 if (!reader) return E_INVALIDARG;
3696 for (i = 0; i < count; i++)
3698 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
3699 properties[i].valueSize );
3700 if (hr != S_OK) return hr;
3703 if ((hr = read_init_state( reader )) != S_OK) return hr;
3705 switch (encoding->encodingType)
3707 case WS_XML_READER_ENCODING_TYPE_TEXT:
3709 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
3710 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
3711 WS_CHARSET charset = text->charSet;
3713 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
3715 FIXME( "charset detection on input type %u not supported\n", input->inputType );
3716 return E_NOTIMPL;
3719 if (charset == WS_CHARSET_AUTO)
3720 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
3722 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
3723 &charset, sizeof(charset) );
3724 if (hr != S_OK) return hr;
3725 break;
3727 default:
3728 FIXME( "encoding type %u not supported\n", encoding->encodingType );
3729 return E_NOTIMPL;
3731 switch (input->inputType)
3733 case WS_XML_READER_INPUT_TYPE_BUFFER:
3735 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
3736 set_input_buffer( reader, (const unsigned char *)buf->encodedData + offset, buf->encodedDataSize - offset );
3737 break;
3739 default:
3740 FIXME( "input type %u not supported\n", input->inputType );
3741 return E_NOTIMPL;
3744 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
3745 read_insert_bof( reader, node );
3746 return S_OK;
3749 /**************************************************************************
3750 * WsSetInputToBuffer [webservices.@]
3752 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
3753 const WS_XML_READER_PROPERTY *properties, ULONG count,
3754 WS_ERROR *error )
3756 struct reader *reader = (struct reader *)handle;
3757 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
3758 WS_CHARSET charset;
3759 struct node *node;
3760 HRESULT hr;
3761 ULONG i, offset = 0;
3763 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
3764 if (error) FIXME( "ignoring error parameter\n" );
3766 if (!reader || !xmlbuf) return E_INVALIDARG;
3768 for (i = 0; i < count; i++)
3770 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
3771 properties[i].valueSize );
3772 if (hr != S_OK) return hr;
3775 if ((hr = read_init_state( reader )) != S_OK) return hr;
3777 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
3778 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
3779 &charset, sizeof(charset) );
3780 if (hr != S_OK) return hr;
3782 set_input_buffer( reader, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
3783 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
3784 read_insert_bof( reader, node );
3785 return S_OK;
3788 /**************************************************************************
3789 * WsXmlStringEquals [webservices.@]
3791 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
3793 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
3794 if (error) FIXME( "ignoring error parameter\n" );
3796 if (!str1 || !str2) return E_INVALIDARG;
3798 if (str1->length != str2->length) return S_FALSE;
3799 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
3800 return S_FALSE;