webservices: Implement WS_MOVE_TO_CHILD_ELEMENT in the reader.
[wine.git] / dlls / webservices / reader.c
blob5b0217f2a73f2e9364c8b2a16101c6ae5079aecf
1 /*
2 * Copyright 2015, 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winnls.h"
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "webservices_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
32 const char *debugstr_xmlstr( const WS_XML_STRING *str )
34 if (!str) return "(null)";
35 return debugstr_an( (const char *)str->bytes, str->length );
38 static const struct
40 ULONG size;
41 BOOL readonly;
43 error_props[] =
45 { sizeof(ULONG), TRUE }, /* WS_ERROR_PROPERTY_STRING_COUNT */
46 { sizeof(ULONG), FALSE }, /* WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE */
47 { sizeof(LANGID), FALSE } /* WS_ERROR_PROPERTY_LANGID */
50 struct error
52 ULONG prop_count;
53 WS_ERROR_PROPERTY prop[sizeof(error_props)/sizeof(error_props[0])];
56 static struct error *alloc_error(void)
58 static const ULONG count = sizeof(error_props)/sizeof(error_props[0]);
59 struct error *ret;
60 ULONG i, size = sizeof(*ret) + count * sizeof(WS_ERROR_PROPERTY);
61 char *ptr;
63 for (i = 0; i < count; i++) size += error_props[i].size;
64 if (!(ret = heap_alloc_zero( size ))) return NULL;
66 ptr = (char *)&ret->prop[count];
67 for (i = 0; i < count; i++)
69 ret->prop[i].value = ptr;
70 ret->prop[i].valueSize = error_props[i].size;
71 ptr += ret->prop[i].valueSize;
73 ret->prop_count = count;
74 return ret;
77 static HRESULT set_error_prop( struct error *error, WS_ERROR_PROPERTY_ID id, const void *value, ULONG size )
79 if (id >= error->prop_count || size != error_props[id].size || error_props[id].readonly)
80 return E_INVALIDARG;
82 memcpy( error->prop[id].value, value, size );
83 return S_OK;
86 static HRESULT get_error_prop( struct error *error, WS_ERROR_PROPERTY_ID id, void *buf, ULONG size )
88 if (id >= error->prop_count || size != error_props[id].size)
89 return E_INVALIDARG;
91 memcpy( buf, error->prop[id].value, error->prop[id].valueSize );
92 return S_OK;
95 /**************************************************************************
96 * WsCreateError [webservices.@]
98 HRESULT WINAPI WsCreateError( const WS_ERROR_PROPERTY *properties, ULONG count, WS_ERROR **handle )
100 struct error *error;
101 LANGID langid = GetUserDefaultUILanguage();
102 HRESULT hr;
103 ULONG i;
105 TRACE( "%p %u %p\n", properties, count, handle );
107 if (!handle) return E_INVALIDARG;
108 if (!(error = alloc_error())) return E_OUTOFMEMORY;
110 set_error_prop( error, WS_ERROR_PROPERTY_LANGID, &langid, sizeof(langid) );
111 for (i = 0; i < count; i++)
113 if (properties[i].id == WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE)
115 heap_free( error );
116 return E_INVALIDARG;
118 hr = set_error_prop( error, properties[i].id, properties[i].value, properties[i].valueSize );
119 if (hr != S_OK)
121 heap_free( error );
122 return hr;
126 *handle = (WS_ERROR *)error;
127 return S_OK;
130 /**************************************************************************
131 * WsFreeError [webservices.@]
133 void WINAPI WsFreeError( WS_ERROR *handle )
135 struct error *error = (struct error *)handle;
137 TRACE( "%p\n", handle );
138 heap_free( error );
141 static const struct
143 ULONG size;
144 BOOL readonly;
146 heap_props[] =
148 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_MAX_SIZE */
149 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_TRIM_SIZE */
150 { sizeof(SIZE_T), TRUE }, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
151 { sizeof(SIZE_T), TRUE } /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
154 struct heap
156 HANDLE handle;
157 ULONG prop_count;
158 WS_HEAP_PROPERTY prop[sizeof(heap_props)/sizeof(heap_props[0])];
161 void *ws_alloc( WS_HEAP *handle, SIZE_T size )
163 struct heap *heap = (struct heap *)handle;
164 return HeapAlloc( heap->handle, 0, size );
167 static void *ws_alloc_zero( WS_HEAP *handle, SIZE_T size )
169 struct heap *heap = (struct heap *)handle;
170 return HeapAlloc( heap->handle, HEAP_ZERO_MEMORY, size );
173 void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
175 struct heap *heap = (struct heap *)handle;
176 return HeapReAlloc( heap->handle, 0, ptr, size );
179 void ws_free( WS_HEAP *handle, void *ptr )
181 struct heap *heap = (struct heap *)handle;
182 HeapFree( heap->handle, 0, ptr );
185 /**************************************************************************
186 * WsAlloc [webservices.@]
188 HRESULT WINAPI WsAlloc( WS_HEAP *handle, SIZE_T size, void **ptr, WS_ERROR *error )
190 void *mem;
192 TRACE( "%p %u %p %p\n", handle, (ULONG)size, ptr, error );
193 if (error) FIXME( "ignoring error parameter\n" );
195 if (!handle || !ptr) return E_INVALIDARG;
197 if (!(mem = ws_alloc( handle, size ))) return E_OUTOFMEMORY;
198 *ptr = mem;
199 return S_OK;
202 static struct heap *alloc_heap(void)
204 static const ULONG count = sizeof(heap_props)/sizeof(heap_props[0]);
205 struct heap *ret;
206 ULONG i, size = sizeof(*ret) + count * sizeof(WS_HEAP_PROPERTY);
207 char *ptr;
209 for (i = 0; i < count; i++) size += heap_props[i].size;
210 if (!(ret = heap_alloc_zero( size ))) return NULL;
212 ptr = (char *)&ret->prop[count];
213 for (i = 0; i < count; i++)
215 ret->prop[i].value = ptr;
216 ret->prop[i].valueSize = heap_props[i].size;
217 ptr += ret->prop[i].valueSize;
219 ret->prop_count = count;
220 return ret;
223 static HRESULT set_heap_prop( struct heap *heap, WS_HEAP_PROPERTY_ID id, const void *value, ULONG size )
225 if (id >= heap->prop_count || size != heap_props[id].size || heap_props[id].readonly)
226 return E_INVALIDARG;
228 memcpy( heap->prop[id].value, value, size );
229 return S_OK;
232 static HRESULT get_heap_prop( struct heap *heap, WS_HEAP_PROPERTY_ID id, void *buf, ULONG size )
234 if (id >= heap->prop_count || size != heap_props[id].size)
235 return E_INVALIDARG;
237 memcpy( buf, heap->prop[id].value, heap->prop[id].valueSize );
238 return S_OK;
241 /**************************************************************************
242 * WsCreateHeap [webservices.@]
244 HRESULT WINAPI WsCreateHeap( SIZE_T max_size, SIZE_T trim_size, const WS_HEAP_PROPERTY *properties,
245 ULONG count, WS_HEAP **handle, WS_ERROR *error )
247 struct heap *heap;
249 TRACE( "%u %u %p %u %p %p\n", (ULONG)max_size, (ULONG)trim_size, properties, count, handle, error );
250 if (error) FIXME( "ignoring error parameter\n" );
252 if (!handle || count) return E_INVALIDARG;
253 if (!(heap = alloc_heap())) return E_OUTOFMEMORY;
255 set_heap_prop( heap, WS_HEAP_PROPERTY_MAX_SIZE, &max_size, sizeof(max_size) );
256 set_heap_prop( heap, WS_HEAP_PROPERTY_TRIM_SIZE, &trim_size, sizeof(trim_size) );
258 if (!(heap->handle = HeapCreate( 0, 0, max_size )))
260 heap_free( heap );
261 return E_OUTOFMEMORY;
264 *handle = (WS_HEAP *)heap;
265 return S_OK;
268 /**************************************************************************
269 * WsFreeHeap [webservices.@]
271 void WINAPI WsFreeHeap( WS_HEAP *handle )
273 struct heap *heap = (struct heap *)handle;
275 TRACE( "%p\n", handle );
277 if (!heap) return;
278 HeapDestroy( heap->handle );
279 heap_free( heap );
282 struct node *alloc_node( WS_XML_NODE_TYPE type )
284 struct node *ret;
286 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
287 ret->hdr.node.nodeType = type;
288 list_init( &ret->entry );
289 list_init( &ret->children );
290 return ret;
293 void free_attribute( WS_XML_ATTRIBUTE *attr )
295 if (!attr) return;
296 heap_free( attr->prefix );
297 heap_free( attr->localName );
298 heap_free( attr->ns );
299 heap_free( attr->value );
300 heap_free( attr );
303 void free_node( struct node *node )
305 if (!node) return;
306 switch (node->hdr.node.nodeType)
308 case WS_XML_NODE_TYPE_ELEMENT:
310 WS_XML_ELEMENT_NODE *elem = &node->hdr;
311 ULONG i;
313 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
314 heap_free( elem->attributes );
315 heap_free( elem->prefix );
316 heap_free( elem->localName );
317 heap_free( elem->ns );
318 break;
320 case WS_XML_NODE_TYPE_TEXT:
322 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
323 heap_free( text->text );
324 break;
326 case WS_XML_NODE_TYPE_COMMENT:
328 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
329 heap_free( comment->value.bytes );
330 break;
332 case WS_XML_NODE_TYPE_CDATA:
333 case WS_XML_NODE_TYPE_END_CDATA:
334 case WS_XML_NODE_TYPE_END_ELEMENT:
335 case WS_XML_NODE_TYPE_EOF:
336 case WS_XML_NODE_TYPE_BOF:
337 break;
339 default:
340 ERR( "unhandled type %u\n", node->hdr.node.nodeType );
341 break;
343 heap_free( node );
346 void destroy_nodes( struct node *node )
348 struct list *ptr;
350 if (!node) return;
351 while ((ptr = list_head( &node->children )))
353 struct node *child = LIST_ENTRY( ptr, struct node, entry );
354 list_remove( &child->entry );
355 destroy_nodes( child );
357 free_node( node );
360 static const struct
362 ULONG size;
363 BOOL readonly;
365 reader_props[] =
367 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
368 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
369 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
370 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
371 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
372 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
373 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
374 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
375 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
376 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
377 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
378 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
379 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
380 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
381 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
384 enum reader_state
386 READER_STATE_INITIAL,
387 READER_STATE_BOF,
388 READER_STATE_STARTELEMENT,
389 READER_STATE_STARTATTRIBUTE,
390 READER_STATE_STARTCDATA,
391 READER_STATE_CDATA,
392 READER_STATE_TEXT,
393 READER_STATE_ENDELEMENT,
394 READER_STATE_ENDCDATA,
395 READER_STATE_COMMENT,
396 READER_STATE_EOF
399 struct reader
401 ULONG read_size;
402 ULONG read_pos;
403 const unsigned char *read_bufptr;
404 enum reader_state state;
405 struct node *root;
406 struct node *current;
407 ULONG current_attr;
408 WS_XML_READER_INPUT_TYPE input_type;
409 const unsigned char *input_data;
410 ULONG input_size;
411 ULONG prop_count;
412 WS_XML_READER_PROPERTY prop[sizeof(reader_props)/sizeof(reader_props[0])];
415 static struct reader *alloc_reader(void)
417 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
418 struct reader *ret;
419 ULONG i, size = sizeof(*ret) + count * sizeof(WS_XML_READER_PROPERTY);
420 char *ptr;
422 for (i = 0; i < count; i++) size += reader_props[i].size;
423 if (!(ret = heap_alloc_zero( size ))) return NULL;
425 ptr = (char *)&ret->prop[count];
426 for (i = 0; i < count; i++)
428 ret->prop[i].value = ptr;
429 ret->prop[i].valueSize = reader_props[i].size;
430 ptr += ret->prop[i].valueSize;
432 ret->prop_count = count;
433 return ret;
436 static HRESULT set_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID id, const void *value, ULONG size )
438 if (id >= reader->prop_count || size != reader_props[id].size || reader_props[id].readonly)
439 return E_INVALIDARG;
441 memcpy( reader->prop[id].value, value, size );
442 return S_OK;
445 static HRESULT get_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID id, void *buf, ULONG size )
447 if (id >= reader->prop_count || size != reader_props[id].size)
448 return E_INVALIDARG;
450 memcpy( buf, reader->prop[id].value, reader->prop[id].valueSize );
451 return S_OK;
454 static void read_insert_eof( struct reader *reader, struct node *eof )
456 if (!reader->root) reader->root = eof;
457 else
459 eof->parent = reader->root;
460 list_add_tail( &reader->root->children, &eof->entry );
462 reader->current = eof;
465 static void read_insert_bof( struct reader *reader, struct node *bof )
467 reader->root->parent = bof;
468 list_add_tail( &bof->children, &reader->root->entry );
469 reader->current = reader->root = bof;
472 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
474 node->parent = parent;
475 if (node->parent == reader->root)
477 struct list *eof = list_tail( &reader->root->children );
478 list_add_before( eof, &node->entry );
480 else list_add_tail( &parent->children, &node->entry );
481 reader->current = node;
484 static HRESULT read_init_state( struct reader *reader )
486 struct node *node;
488 destroy_nodes( reader->root );
489 reader->root = NULL;
490 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
491 read_insert_eof( reader, node );
492 reader->state = READER_STATE_INITIAL;
493 return S_OK;
496 /**************************************************************************
497 * WsCreateReader [webservices.@]
499 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
500 WS_XML_READER **handle, WS_ERROR *error )
502 struct reader *reader;
503 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
504 WS_CHARSET charset = WS_CHARSET_UTF8;
505 BOOL read_decl = TRUE;
506 HRESULT hr;
508 TRACE( "%p %u %p %p\n", properties, count, handle, error );
509 if (error) FIXME( "ignoring error parameter\n" );
511 if (!handle) return E_INVALIDARG;
512 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
514 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
515 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
516 set_reader_prop( reader, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
517 set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
518 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
520 for (i = 0; i < count; i++)
522 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
523 if (hr != S_OK)
525 heap_free( reader );
526 return hr;
530 if ((hr = read_init_state( reader )) != S_OK)
532 heap_free( reader );
533 return hr;
536 *handle = (WS_XML_READER *)reader;
537 return S_OK;
540 /**************************************************************************
541 * WsFreeReader [webservices.@]
543 void WINAPI WsFreeReader( WS_XML_READER *handle )
545 struct reader *reader = (struct reader *)handle;
547 TRACE( "%p\n", handle );
549 if (!reader) return;
550 destroy_nodes( reader->root );
551 heap_free( reader );
554 /**************************************************************************
555 * WsFillReader [webservices.@]
557 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
558 WS_ERROR *error )
560 struct reader *reader = (struct reader *)handle;
562 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
563 if (error) FIXME( "ignoring error parameter\n" );
565 if (!reader) return E_INVALIDARG;
567 /* FIXME: add support for stream input */
568 reader->read_size = min( min_size, reader->input_size );
569 reader->read_pos = 0;
571 return S_OK;
574 /**************************************************************************
575 * WsGetErrorProperty [webservices.@]
577 HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf,
578 ULONG size )
580 struct error *error = (struct error *)handle;
582 TRACE( "%p %u %p %u\n", handle, id, buf, size );
583 return get_error_prop( error, id, buf, size );
586 /**************************************************************************
587 * WsGetErrorString [webservices.@]
589 HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str )
591 FIXME( "%p %u %p: stub\n", handle, index, str );
592 return E_NOTIMPL;
595 /**************************************************************************
596 * WsGetHeapProperty [webservices.@]
598 HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
599 ULONG size, WS_ERROR *error )
601 struct heap *heap = (struct heap *)handle;
603 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
604 if (error) FIXME( "ignoring error parameter\n" );
606 return get_heap_prop( heap, id, buf, size );
609 /**************************************************************************
610 * WsGetReaderNode [webservices.@]
612 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
613 WS_ERROR *error )
615 struct reader *reader = (struct reader *)handle;
617 TRACE( "%p %p %p\n", handle, node, error );
618 if (error) FIXME( "ignoring error parameter\n" );
620 if (!reader || !node) return E_INVALIDARG;
622 *node = &reader->current->hdr.node;
623 return S_OK;
626 /**************************************************************************
627 * WsGetReaderProperty [webservices.@]
629 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
630 void *buf, ULONG size, WS_ERROR *error )
632 struct reader *reader = (struct reader *)handle;
634 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
635 if (error) FIXME( "ignoring error parameter\n" );
637 if (!reader->input_type) return WS_E_INVALID_OPERATION;
639 if (id == WS_XML_READER_PROPERTY_CHARSET)
641 WS_CHARSET charset;
642 HRESULT hr;
644 if ((hr = get_reader_prop( reader, id, &charset, size )) != S_OK) return hr;
645 if (!charset) return WS_E_INVALID_FORMAT;
646 *(WS_CHARSET *)buf = charset;
647 return S_OK;
649 return get_reader_prop( reader, id, buf, size );
652 /**************************************************************************
653 * WsGetXmlAttribute [webservices.@]
655 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
656 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
658 FIXME( "%p %p %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
659 return E_NOTIMPL;
662 WS_XML_STRING *alloc_xml_string( const unsigned char *data, ULONG len )
664 WS_XML_STRING *ret;
666 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
667 ret->length = len;
668 ret->bytes = (BYTE *)(ret + 1);
669 ret->dictionary = NULL;
670 ret->id = 0;
671 if (data) memcpy( ret->bytes, data, len );
672 return ret;
675 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *data, ULONG len )
677 WS_XML_UTF8_TEXT *ret;
679 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
680 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
681 ret->value.length = len;
682 ret->value.bytes = (BYTE *)(ret + 1);
683 ret->value.dictionary = NULL;
684 ret->value.id = 0;
685 if (data) memcpy( ret->value.bytes, data, len );
686 return ret;
689 static inline BOOL read_end_of_data( struct reader *reader )
691 return reader->read_pos >= reader->read_size;
694 static inline const unsigned char *read_current_ptr( struct reader *reader )
696 return &reader->read_bufptr[reader->read_pos];
699 /* UTF-8 support based on libs/wine/utf8.c */
701 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
702 static const char utf8_length[128] =
704 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
705 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
706 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
707 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
708 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
709 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
710 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
711 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
714 /* first byte mask depending on UTF-8 sequence length */
715 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
717 /* minimum Unicode value depending on UTF-8 sequence length */
718 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
720 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
722 unsigned int len, res;
723 unsigned char ch = reader->read_bufptr[reader->read_pos];
724 const unsigned char *end;
726 if (reader->read_pos >= reader->read_size) return 0;
728 if (ch < 0x80)
730 *skip = 1;
731 return ch;
733 len = utf8_length[ch - 0x80];
734 if (reader->read_pos + len >= reader->read_size) return 0;
735 end = reader->read_bufptr + reader->read_pos + len;
736 res = ch & utf8_mask[len];
738 switch (len)
740 case 3:
741 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
742 res = (res << 6) | ch;
743 case 2:
744 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
745 res = (res << 6) | ch;
746 case 1:
747 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
748 res = (res << 6) | ch;
749 if (res < utf8_minval[len]) break;
750 *skip = len + 1;
751 return res;
754 return 0;
757 static inline void read_skip( struct reader *reader, unsigned int count )
759 while (reader->read_pos < reader->read_size && count)
761 reader->read_pos++;
762 count--;
766 static inline BOOL read_isnamechar( unsigned int ch )
768 /* FIXME: incomplete */
769 return (ch >= 'A' && ch <= 'Z') ||
770 (ch >= 'a' && ch <= 'z') ||
771 (ch >= '0' && ch <= '9') ||
772 ch == '_' || ch == '-' || ch == '.' || ch == ':';
775 static inline BOOL read_isspace( unsigned int ch )
777 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
780 static inline void read_skip_whitespace( struct reader *reader )
782 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
783 reader->read_pos++;
786 static inline int read_cmp( struct reader *reader, const char *str, int len )
788 const unsigned char *ptr = read_current_ptr( reader );
790 if (len < 0) len = strlen( str );
791 if (reader->read_pos + len > reader->read_size) return -1;
792 while (len--)
794 if (*str != *ptr) return *ptr - *str;
795 str++; ptr++;
797 return 0;
800 static HRESULT read_xmldecl( struct reader *reader )
802 if (!reader->read_size) return WS_E_INVALID_FORMAT;
804 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
806 reader->state = READER_STATE_BOF;
807 return S_OK;
809 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
810 read_skip( reader, 6 );
812 /* FIXME: parse attributes */
813 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
814 reader->read_pos++;
816 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
817 read_skip( reader, 2 );
819 reader->state = READER_STATE_BOF;
820 return S_OK;
823 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
825 if (elem->attributeCount)
827 WS_XML_ATTRIBUTE **tmp;
828 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
829 return E_OUTOFMEMORY;
830 elem->attributes = tmp;
832 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
833 elem->attributes[elem->attributeCount++] = attr;
834 return S_OK;
837 static HRESULT parse_name( const unsigned char *str, unsigned int len,
838 WS_XML_STRING **prefix, WS_XML_STRING **localname )
840 const unsigned char *name_ptr = str, *prefix_ptr = NULL;
841 unsigned int i, name_len = len, prefix_len = 0;
843 for (i = 0; i < len; i++)
845 if (str[i] == ':')
847 prefix_ptr = str;
848 prefix_len = i;
849 name_ptr = &str[i + 1];
850 name_len -= i + 1;
851 break;
854 if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
855 if (!(*localname = alloc_xml_string( name_ptr, name_len )))
857 heap_free( *prefix );
858 return E_OUTOFMEMORY;
860 return S_OK;
863 static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
865 WS_XML_ATTRIBUTE *attr;
866 WS_XML_UTF8_TEXT *text;
867 unsigned int len = 0, ch, skip, quote;
868 const unsigned char *start;
869 HRESULT hr = WS_E_INVALID_FORMAT;
871 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
873 start = read_current_ptr( reader );
874 for (;;)
876 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
877 if (!read_isnamechar( ch )) break;
878 read_skip( reader, skip );
879 len += skip;
881 if (!len) goto error;
883 if ((hr = parse_name( start, len, &attr->prefix, &attr->localName )) != S_OK) goto error;
884 if (!attr->prefix->length) attr->prefix->bytes = NULL;
885 hr = E_OUTOFMEMORY;
886 if (!(attr->ns = alloc_xml_string( NULL, 0 ))) goto error;
887 attr->ns->bytes = NULL;
889 hr = WS_E_INVALID_FORMAT;
890 read_skip_whitespace( reader );
891 if (read_cmp( reader, "=", 1 )) goto error;
892 read_skip( reader, 1 );
894 read_skip_whitespace( reader );
895 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) goto error;
896 quote = read_utf8_char( reader, &skip );
897 read_skip( reader, 1 );
899 len = 0;
900 start = read_current_ptr( reader );
901 for (;;)
903 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
904 if (ch == quote) break;
905 read_skip( reader, skip );
906 len += skip;
908 read_skip( reader, 1 );
910 if (!(text = alloc_utf8_text( start, len )))
912 free_attribute( attr );
913 return E_OUTOFMEMORY;
915 attr->value = &text->text;
916 attr->singleQuote = (quote == '\'');
918 *ret = attr;
919 return S_OK;
921 error:
922 free_attribute( attr );
923 return hr;
926 static HRESULT read_element( struct reader *reader )
928 unsigned int len = 0, ch, skip;
929 const unsigned char *start;
930 struct node *node;
931 WS_XML_ELEMENT_NODE *elem;
932 WS_XML_ATTRIBUTE *attr;
933 HRESULT hr = WS_E_INVALID_FORMAT;
935 if (read_end_of_data( reader ))
937 struct list *eof = list_tail( &reader->root->children );
938 reader->current = LIST_ENTRY( eof, struct node, entry );
939 reader->state = READER_STATE_EOF;
940 return S_OK;
943 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
944 elem = (WS_XML_ELEMENT_NODE *)node;
946 if (read_cmp( reader, "<", 1 )) goto error;
947 read_skip( reader, 1 );
949 start = read_current_ptr( reader );
950 for (;;)
952 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
953 if (!read_isnamechar( ch )) break;
954 read_skip( reader, skip );
955 len += skip;
957 if (!len) goto error;
959 if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
960 if (!elem->prefix->length) elem->prefix->bytes = NULL;
961 hr = E_OUTOFMEMORY;
962 if (!(elem->ns = alloc_xml_string( NULL, 0 ))) goto error;
964 reader->current_attr = 0;
965 for (;;)
967 read_skip_whitespace( reader );
968 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
969 if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
970 if ((hr = append_attribute( elem, attr )) != S_OK)
972 free_attribute( attr );
973 goto error;
975 reader->current_attr++;
978 read_skip_whitespace( reader );
979 if (read_cmp( reader, ">", 1 ) && read_cmp( reader, "/>", 2 ))
981 hr = WS_E_INVALID_FORMAT;
982 goto error;
985 read_insert_node( reader, reader->current, node );
986 if (!read_cmp( reader, "/>", 2 ))
988 read_skip( reader, 2 );
989 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
990 read_insert_node( reader, reader->current, node );
991 reader->state = READER_STATE_ENDELEMENT;
993 else
995 read_skip( reader, 1 );
996 reader->state = READER_STATE_STARTELEMENT;
998 return S_OK;
1000 error:
1001 free_node( node );
1002 return hr;
1005 static HRESULT read_text( struct reader *reader )
1007 unsigned int len = 0, ch, skip;
1008 const unsigned char *start;
1009 struct node *node;
1010 WS_XML_TEXT_NODE *text;
1011 WS_XML_UTF8_TEXT *utf8;
1013 start = read_current_ptr( reader );
1014 for (;;)
1016 if (read_end_of_data( reader )) break;
1017 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1018 if (ch == '<') break;
1019 read_skip( reader, skip );
1020 len += skip;
1023 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1024 text = (WS_XML_TEXT_NODE *)node;
1025 if (!(utf8 = alloc_utf8_text( start, len )))
1027 heap_free( node );
1028 return E_OUTOFMEMORY;
1030 text->text = &utf8->text;
1032 read_insert_node( reader, reader->current, node );
1033 reader->state = READER_STATE_TEXT;
1034 return S_OK;
1037 static HRESULT read_startelement( struct reader *reader )
1039 if (!read_cmp( reader, "<", 1 )) return read_element( reader );
1040 return read_text( reader );
1043 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
1045 HRESULT hr;
1047 switch (reader->state)
1049 case READER_STATE_INITIAL:
1050 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
1051 break;
1053 case READER_STATE_STARTELEMENT:
1054 if (found) *found = TRUE;
1055 return S_OK;
1057 default:
1058 break;
1061 read_skip_whitespace( reader );
1062 if ((hr = read_element( reader )) == S_OK && found)
1064 if (reader->state == READER_STATE_STARTELEMENT)
1065 *found = TRUE;
1066 else
1067 *found = FALSE;
1070 return hr;
1073 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
1075 ULONG i;
1076 if (len1 != len2) return 1;
1077 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
1078 return 0;
1081 struct node *find_parent_element( struct node *node, const WS_XML_STRING *prefix,
1082 const WS_XML_STRING *localname )
1084 struct node *parent;
1085 const WS_XML_STRING *str;
1087 for (parent = node; parent; parent = parent->parent)
1089 if (parent->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT) continue;
1090 if (!localname) return parent;
1092 str = parent->hdr.prefix;
1093 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
1095 str = parent->hdr.localName;
1096 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
1098 return parent;
1100 return NULL;
1103 static HRESULT read_endelement( struct reader *reader )
1105 struct node *node, *parent;
1106 unsigned int len = 0, ch, skip;
1107 const unsigned char *start;
1108 WS_XML_STRING *prefix, *localname;
1109 HRESULT hr;
1111 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
1112 read_skip( reader, 2 );
1114 start = read_current_ptr( reader );
1115 for (;;)
1117 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1118 if (ch == '>')
1120 read_skip( reader, 1 );
1121 break;
1123 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
1124 read_skip( reader, skip );
1125 len += skip;
1128 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
1129 parent = find_parent_element( reader->current, prefix, localname );
1130 heap_free( prefix );
1131 heap_free( localname );
1132 if (!parent) return WS_E_INVALID_FORMAT;
1134 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1135 read_insert_node( reader, parent, node );
1136 reader->state = READER_STATE_ENDELEMENT;
1137 return S_OK;
1140 static HRESULT read_comment( struct reader *reader )
1142 unsigned int len = 0, ch, skip;
1143 const unsigned char *start;
1144 struct node *node;
1145 WS_XML_COMMENT_NODE *comment;
1147 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
1148 read_skip( reader, 4 );
1150 start = read_current_ptr( reader );
1151 for (;;)
1153 if (!read_cmp( reader, "-->", 3 ))
1155 read_skip( reader, 3 );
1156 break;
1158 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1159 read_skip( reader, skip );
1160 len += skip;
1163 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
1164 comment = (WS_XML_COMMENT_NODE *)node;
1165 if (!(comment->value.bytes = heap_alloc( len )))
1167 heap_free( node );
1168 return E_OUTOFMEMORY;
1170 memcpy( comment->value.bytes, start, len );
1171 comment->value.length = len;
1173 read_insert_node( reader, reader->current, node );
1174 reader->state = READER_STATE_COMMENT;
1175 return S_OK;
1178 static HRESULT read_startcdata( struct reader *reader )
1180 struct node *node;
1182 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
1183 read_skip( reader, 9 );
1185 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
1186 read_insert_node( reader, reader->current, node );
1187 reader->state = READER_STATE_STARTCDATA;
1188 return S_OK;
1191 static HRESULT read_cdata( struct reader *reader )
1193 unsigned int len = 0, ch, skip;
1194 const unsigned char *start;
1195 struct node *node;
1196 WS_XML_TEXT_NODE *text;
1197 WS_XML_UTF8_TEXT *utf8;
1199 start = read_current_ptr( reader );
1200 for (;;)
1202 if (!read_cmp( reader, "]]>", 3 )) break;
1203 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1204 read_skip( reader, skip );
1205 len += skip;
1208 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1209 text = (WS_XML_TEXT_NODE *)node;
1210 if (!(utf8 = alloc_utf8_text( start, len )))
1212 heap_free( node );
1213 return E_OUTOFMEMORY;
1215 text->text = &utf8->text;
1217 read_insert_node( reader, reader->current, node );
1218 reader->state = READER_STATE_CDATA;
1219 return S_OK;
1222 static HRESULT read_endcdata( struct reader *reader )
1224 struct node *node;
1226 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
1227 read_skip( reader, 3 );
1229 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_CDATA ))) return E_OUTOFMEMORY;
1230 read_insert_node( reader, reader->current->parent, node );
1231 reader->state = READER_STATE_ENDCDATA;
1232 return S_OK;
1235 static HRESULT read_node( struct reader *reader )
1237 HRESULT hr;
1239 for (;;)
1241 if (read_end_of_data( reader ))
1243 struct list *eof = list_tail( &reader->root->children );
1244 reader->current = LIST_ENTRY( eof, struct node, entry );
1245 reader->state = READER_STATE_EOF;
1246 return S_OK;
1248 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
1249 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
1250 else if (!read_cmp( reader, "<?", 2 ))
1252 hr = read_xmldecl( reader );
1253 if (FAILED( hr )) return hr;
1255 else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
1256 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
1257 else if (!read_cmp( reader, "<!--", 4 )) return read_comment( reader );
1258 else if (!read_cmp( reader, "<", 1 )) return read_startelement( reader );
1259 else return read_text( reader );
1263 /**************************************************************************
1264 * WsReadEndElement [webservices.@]
1266 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
1268 struct reader *reader = (struct reader *)handle;
1270 TRACE( "%p %p\n", handle, error );
1271 if (error) FIXME( "ignoring error parameter\n" );
1273 if (!reader) return E_INVALIDARG;
1274 return read_endelement( reader );
1277 /**************************************************************************
1278 * WsReadNode [webservices.@]
1280 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
1282 struct reader *reader = (struct reader *)handle;
1284 TRACE( "%p %p\n", handle, error );
1285 if (error) FIXME( "ignoring error parameter\n" );
1287 if (!reader) return E_INVALIDARG;
1288 return read_node( reader );
1291 /**************************************************************************
1292 * WsReadStartElement [webservices.@]
1294 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
1296 struct reader *reader = (struct reader *)handle;
1298 TRACE( "%p %p\n", handle, error );
1299 if (error) FIXME( "ignoring error parameter\n" );
1301 if (!reader) return E_INVALIDARG;
1302 return read_startelement( reader );
1305 /**************************************************************************
1306 * WsReadToStartElement [webservices.@]
1308 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
1309 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
1311 struct reader *reader = (struct reader *)handle;
1313 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
1314 if (error) FIXME( "ignoring error parameter\n" );
1316 if (!reader) return E_INVALIDARG;
1317 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
1319 return read_to_startelement( reader, found );
1322 static BOOL move_to_root_element( struct reader *reader )
1324 struct list *ptr;
1325 struct node *node;
1327 if (!(ptr = list_head( &reader->root->children ))) return FALSE;
1328 node = LIST_ENTRY( ptr, struct node, entry );
1329 if (node->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1331 reader->current = node;
1332 return TRUE;
1334 while ((ptr = list_next( &reader->root->children, &node->entry )))
1336 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1337 if (next->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1339 reader->current = next;
1340 return TRUE;
1342 node = next;
1344 return FALSE;
1347 static BOOL move_to_next_element( struct reader *reader )
1349 struct list *ptr;
1350 struct node *node = reader->current;
1352 while ((ptr = list_next( &node->parent->children, &node->entry )))
1354 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1355 if (next->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1357 reader->current = next;
1358 return TRUE;
1360 node = next;
1362 return FALSE;
1365 static BOOL move_to_prev_element( struct reader *reader )
1367 struct list *ptr;
1368 struct node *node = reader->current;
1370 while ((ptr = list_prev( &node->parent->children, &node->entry )))
1372 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
1373 if (prev->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1375 reader->current = prev;
1376 return TRUE;
1378 node = prev;
1380 return FALSE;
1383 static BOOL move_to_child_element( struct reader *reader )
1385 struct list *ptr;
1386 struct node *node;
1388 if (!(ptr = list_head( &reader->current->children ))) return FALSE;
1389 node = LIST_ENTRY( ptr, struct node, entry );
1390 if (node->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1392 reader->current = node;
1393 return TRUE;
1395 while ((ptr = list_next( &reader->current->children, &node->entry )))
1397 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1398 if (next->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
1400 reader->current = next;
1401 return TRUE;
1403 node = next;
1405 return FALSE;
1408 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
1410 struct list *ptr;
1411 BOOL success = FALSE;
1412 HRESULT hr = S_OK;
1414 if (!read_end_of_data( reader ))
1416 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
1417 if (hr != S_OK) return hr;
1419 switch (move)
1421 case WS_MOVE_TO_ROOT_ELEMENT:
1422 success = move_to_root_element( reader );
1423 break;
1425 case WS_MOVE_TO_NEXT_ELEMENT:
1426 success = move_to_next_element( reader );
1427 break;
1429 case WS_MOVE_TO_PREVIOUS_ELEMENT:
1430 success = move_to_prev_element( reader );
1431 break;
1433 case WS_MOVE_TO_CHILD_ELEMENT:
1434 success = move_to_child_element( reader );
1435 break;
1437 case WS_MOVE_TO_FIRST_NODE:
1438 if ((ptr = list_head( &reader->current->parent->children )))
1440 reader->current = LIST_ENTRY( ptr, struct node, entry );
1441 success = TRUE;
1443 break;
1445 case WS_MOVE_TO_NEXT_NODE:
1446 if ((ptr = list_next( &reader->current->parent->children, &reader->current->entry )))
1448 reader->current = LIST_ENTRY( ptr, struct node, entry );
1449 success = TRUE;
1451 break;
1453 case WS_MOVE_TO_PREVIOUS_NODE:
1454 if ((ptr = list_prev( &reader->current->parent->children, &reader->current->entry )))
1456 reader->current = LIST_ENTRY( ptr, struct node, entry );
1457 success = TRUE;
1459 break;
1461 case WS_MOVE_TO_CHILD_NODE:
1462 if ((ptr = list_head( &reader->current->children )))
1464 reader->current = LIST_ENTRY( ptr, struct node, entry );
1465 success = TRUE;
1467 break;
1469 case WS_MOVE_TO_BOF:
1470 reader->current = reader->root;
1471 success = TRUE;
1472 break;
1474 case WS_MOVE_TO_EOF:
1475 if ((ptr = list_tail( &reader->root->children )))
1477 reader->current = LIST_ENTRY( ptr, struct node, entry );
1478 success = TRUE;
1480 break;
1482 default:
1483 FIXME( "unhandled move %u\n", move );
1484 return E_NOTIMPL;
1487 if (found)
1489 *found = success;
1490 return S_OK;
1492 return success ? S_OK : WS_E_INVALID_FORMAT;
1495 /**************************************************************************
1496 * WsMoveReader [webservices.@]
1498 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
1500 struct reader *reader = (struct reader *)handle;
1502 TRACE( "%p %u %p %p\n", handle, move, found, error );
1503 if (error) FIXME( "ignoring error parameter\n" );
1505 if (!reader) return E_INVALIDARG;
1506 if (!reader->input_type) return WS_E_INVALID_OPERATION;
1508 return read_move_to( reader, move, found );
1511 /**************************************************************************
1512 * WsReadStartAttribute [webservices.@]
1514 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
1516 struct reader *reader = (struct reader *)handle;
1517 WS_XML_ELEMENT_NODE *elem;
1519 TRACE( "%p %u %p\n", handle, index, error );
1520 if (error) FIXME( "ignoring error parameter\n" );
1522 if (!reader) return E_INVALIDARG;
1524 elem = &reader->current->hdr;
1525 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
1526 return WS_E_INVALID_FORMAT;
1528 reader->current_attr = index;
1529 reader->state = READER_STATE_STARTATTRIBUTE;
1530 return S_OK;
1533 /**************************************************************************
1534 * WsReadEndAttribute [webservices.@]
1536 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
1538 struct reader *reader = (struct reader *)handle;
1540 TRACE( "%p %p\n", handle, error );
1541 if (error) FIXME( "ignoring error parameter\n" );
1543 if (!reader) return E_INVALIDARG;
1545 if (reader->state != READER_STATE_STARTATTRIBUTE)
1546 return WS_E_INVALID_FORMAT;
1548 reader->state = READER_STATE_STARTELEMENT;
1549 return S_OK;
1552 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
1554 WCHAR *ret;
1556 switch (text->textType)
1558 case WS_XML_TEXT_TYPE_UTF8:
1560 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
1561 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
1562 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
1563 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
1564 ret[len] = 0;
1565 break;
1567 default:
1568 FIXME( "unhandled type %u\n", text->textType );
1569 return NULL;
1572 return ret;
1575 #define MAX_INT8 0x7f
1576 #define MIN_INT8 (-MAX_INT8 - 1)
1577 #define MAX_INT16 0x7fff
1578 #define MIN_INT16 (-MAX_INT16 - 1)
1579 #define MAX_INT32 0x7fffffff
1580 #define MIN_INT32 (-MAX_INT32 - 1)
1581 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1582 #define MIN_INT64 (-MAX_INT64 - 1)
1583 #define MAX_UINT8 0xff
1584 #define MAX_UINT16 0xffff
1585 #define MAX_UINT32 0xffffffff
1586 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1588 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
1590 BOOL negative = FALSE;
1591 const unsigned char *ptr = str;
1593 *ret = 0;
1594 while (len && read_isspace( *ptr )) { ptr++; len--; }
1595 while (len && read_isspace( ptr[len - 1] )) { len--; }
1596 if (!len) return WS_E_INVALID_FORMAT;
1598 if (*ptr == '-')
1600 negative = TRUE;
1601 ptr++;
1602 len--;
1604 if (!len) return WS_E_INVALID_FORMAT;
1606 while (len--)
1608 int val;
1610 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1611 val = *ptr - '0';
1612 if (negative) val = -val;
1614 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
1615 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
1617 return WS_E_NUMERIC_OVERFLOW;
1619 *ret = *ret * 10 + val;
1620 ptr++;
1623 return S_OK;
1626 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
1628 const unsigned char *ptr = str;
1630 *ret = 0;
1631 while (len && read_isspace( *ptr )) { ptr++; len--; }
1632 while (len && read_isspace( ptr[len - 1] )) { len--; }
1633 if (!len) return WS_E_INVALID_FORMAT;
1635 while (len--)
1637 unsigned int val;
1639 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1640 val = *ptr - '0';
1642 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
1643 *ret = *ret * 10 + val;
1644 ptr++;
1647 return S_OK;
1650 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
1652 WS_XML_TEXT_NODE *text;
1654 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_TEXT)
1655 return WS_E_INVALID_FORMAT;
1657 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
1658 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
1660 FIXME( "text type %u not supported\n", text->text->textType );
1661 return E_NOTIMPL;
1663 *ret = (WS_XML_UTF8_TEXT *)text->text;
1664 return S_OK;
1667 static HRESULT read_get_attribute_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
1669 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1670 WS_XML_ATTRIBUTE *attr;
1672 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT ||
1673 reader->current_attr >= elem->attributeCount) return WS_E_INVALID_FORMAT;
1675 attr = elem->attributes[reader->current_attr];
1676 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
1678 FIXME( "text type %u not supported\n", attr->value->textType );
1679 return E_NOTIMPL;
1681 *ret = (WS_XML_UTF8_TEXT *)attr->value;
1682 reader->current_attr++;
1683 return S_OK;
1686 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
1687 const WS_XML_STRING *ns, ULONG *index )
1689 ULONG i;
1690 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1692 if (!localname)
1694 *index = reader->current_attr;
1695 return TRUE;
1697 for (i = 0; i < elem->attributeCount; i++)
1699 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
1700 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
1702 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
1703 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
1705 *index = i;
1706 return TRUE;
1709 return FALSE;
1712 /**************************************************************************
1713 * WsFindAttribute [webservices.@]
1715 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
1716 const WS_XML_STRING *ns, BOOL required, ULONG *index,
1717 WS_ERROR *error )
1719 struct reader *reader = (struct reader *)handle;
1721 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
1722 required, index, error );
1723 if (error) FIXME( "ignoring error parameter\n" );
1725 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
1727 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT)
1728 return WS_E_INVALID_OPERATION;
1730 if (!find_attribute( reader, localname, ns, index ))
1732 if (required) return WS_E_INVALID_FORMAT;
1733 *index = ~0u;
1734 return S_FALSE;
1736 return S_OK;
1739 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
1740 const WS_BOOL_DESCRIPTION *desc, BOOL *ret )
1742 WS_XML_UTF8_TEXT *utf8;
1743 HRESULT hr;
1744 ULONG len;
1746 if (desc)
1748 FIXME( "description not supported\n" );
1749 return E_NOTIMPL;
1751 switch (mapping)
1753 case WS_ATTRIBUTE_TYPE_MAPPING:
1754 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1755 len = utf8->value.length;
1756 break;
1758 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1759 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1760 len = utf8->value.length;
1761 break;
1763 default:
1764 FIXME( "mapping %u not supported\n", mapping );
1765 return E_NOTIMPL;
1768 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) *ret = TRUE;
1769 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) *ret = TRUE;
1770 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) *ret = FALSE;
1771 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) *ret = FALSE;
1772 else return WS_E_INVALID_FORMAT;
1774 return S_OK;
1777 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
1778 const WS_INT8_DESCRIPTION *desc, INT8 *ret )
1780 WS_XML_UTF8_TEXT *utf8;
1781 HRESULT hr;
1782 INT64 val;
1784 if (desc)
1786 FIXME( "description not supported\n" );
1787 return E_NOTIMPL;
1789 switch (mapping)
1791 case WS_ATTRIBUTE_TYPE_MAPPING:
1792 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1793 break;
1795 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1796 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1797 break;
1799 default:
1800 FIXME( "mapping %u not supported\n", mapping );
1801 return E_NOTIMPL;
1804 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
1805 return hr;
1807 *ret = val;
1808 return S_OK;
1811 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
1812 const WS_INT16_DESCRIPTION *desc, INT16 *ret )
1814 WS_XML_UTF8_TEXT *utf8;
1815 HRESULT hr;
1816 INT64 val;
1818 if (desc)
1820 FIXME( "description not supported\n" );
1821 return E_NOTIMPL;
1823 switch (mapping)
1825 case WS_ATTRIBUTE_TYPE_MAPPING:
1826 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1827 break;
1829 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1830 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1831 break;
1833 default:
1834 FIXME( "mapping %u not supported\n", mapping );
1835 return E_NOTIMPL;
1838 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
1839 return hr;
1841 *ret = val;
1842 return S_OK;
1845 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
1846 const WS_INT32_DESCRIPTION *desc, INT32 *ret )
1848 WS_XML_UTF8_TEXT *utf8;
1849 HRESULT hr;
1850 INT64 val;
1852 if (desc)
1854 FIXME( "description not supported\n" );
1855 return E_NOTIMPL;
1857 switch (mapping)
1859 case WS_ATTRIBUTE_TYPE_MAPPING:
1860 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1861 break;
1863 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1864 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1865 break;
1867 default:
1868 FIXME( "mapping %u not supported\n", mapping );
1869 return E_NOTIMPL;
1872 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
1873 return hr;
1875 *ret = val;
1876 return S_OK;
1879 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
1880 const WS_INT64_DESCRIPTION *desc, INT64 *ret )
1882 WS_XML_UTF8_TEXT *utf8;
1883 HRESULT hr;
1884 INT64 val;
1886 if (desc)
1888 FIXME( "description not supported\n" );
1889 return E_NOTIMPL;
1891 switch (mapping)
1893 case WS_ATTRIBUTE_TYPE_MAPPING:
1894 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1895 break;
1897 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1898 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1899 break;
1901 default:
1902 FIXME( "mapping %u not supported\n", mapping );
1903 return E_NOTIMPL;
1906 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
1907 return hr;
1909 *ret = val;
1910 return S_OK;
1913 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
1914 const WS_UINT8_DESCRIPTION *desc, UINT8 *ret )
1916 WS_XML_UTF8_TEXT *utf8;
1917 HRESULT hr;
1918 UINT64 val;
1920 if (desc)
1922 FIXME( "description not supported\n" );
1923 return E_NOTIMPL;
1925 switch (mapping)
1927 case WS_ATTRIBUTE_TYPE_MAPPING:
1928 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1929 break;
1931 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1932 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1933 break;
1935 default:
1936 FIXME( "mapping %u not supported\n", mapping );
1937 return E_NOTIMPL;
1940 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
1941 return hr;
1943 *ret = val;
1944 return S_OK;
1947 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
1948 const WS_UINT16_DESCRIPTION *desc, UINT16 *ret )
1950 WS_XML_UTF8_TEXT *utf8;
1951 HRESULT hr;
1952 UINT64 val;
1954 if (desc)
1956 FIXME( "description not supported\n" );
1957 return E_NOTIMPL;
1959 switch (mapping)
1961 case WS_ATTRIBUTE_TYPE_MAPPING:
1962 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1963 break;
1965 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1966 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1967 break;
1969 default:
1970 FIXME( "mapping %u not supported\n", mapping );
1971 return E_NOTIMPL;
1974 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
1975 return hr;
1977 *ret = val;
1978 return S_OK;
1981 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
1982 const WS_UINT32_DESCRIPTION *desc, UINT32 *ret )
1984 WS_XML_UTF8_TEXT *utf8;
1985 HRESULT hr;
1986 UINT64 val;
1988 if (desc)
1990 FIXME( "description not supported\n" );
1991 return E_NOTIMPL;
1993 switch (mapping)
1995 case WS_ATTRIBUTE_TYPE_MAPPING:
1996 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1997 break;
1999 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2000 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2001 break;
2003 default:
2004 FIXME( "mapping %u not supported\n", mapping );
2005 return E_NOTIMPL;
2008 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
2009 return hr;
2011 *ret = val;
2012 return S_OK;
2015 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
2016 const WS_UINT64_DESCRIPTION *desc, UINT64 *ret )
2018 WS_XML_UTF8_TEXT *utf8;
2019 HRESULT hr;
2020 UINT64 val;
2022 if (desc)
2024 FIXME( "description not supported\n" );
2025 return E_NOTIMPL;
2027 switch (mapping)
2029 case WS_ATTRIBUTE_TYPE_MAPPING:
2030 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
2031 break;
2033 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2034 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2035 break;
2037 default:
2038 FIXME( "mapping %u not supported\n", mapping );
2039 return E_NOTIMPL;
2042 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
2043 return hr;
2045 *ret = val;
2046 return S_OK;
2049 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
2050 const WS_WSZ_DESCRIPTION *desc, WS_HEAP *heap, WCHAR **ret )
2052 WS_XML_UTF8_TEXT *utf8;
2053 HRESULT hr;
2054 WCHAR *str;
2056 if (desc)
2058 FIXME( "description not supported\n" );
2059 return E_NOTIMPL;
2061 switch (mapping)
2063 case WS_ATTRIBUTE_TYPE_MAPPING:
2064 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
2065 break;
2067 case WS_ELEMENT_TYPE_MAPPING:
2068 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2069 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
2070 break;
2072 default:
2073 FIXME( "mapping %u not supported\n", mapping );
2074 return E_NOTIMPL;
2077 if (!(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
2078 *ret = str;
2079 return S_OK;
2082 static HRESULT read_type_struct( struct reader *, WS_TYPE_MAPPING, const WS_STRUCT_DESCRIPTION *,
2083 WS_HEAP *, void ** );
2085 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
2086 WS_HEAP *heap, char *buf )
2088 char *ptr = buf + desc->offset;
2089 WS_TYPE_MAPPING mapping;
2090 HRESULT hr;
2092 if (desc->options && desc->options != WS_FIELD_POINTER &&
2093 desc->options != WS_FIELD_OPTIONAL &&
2094 desc->options != (WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
2096 FIXME( "options 0x%x not supported\n", desc->options );
2097 return E_NOTIMPL;
2100 switch (desc->mapping)
2102 case WS_ATTRIBUTE_FIELD_MAPPING:
2103 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
2104 break;
2106 case WS_ELEMENT_FIELD_MAPPING:
2107 mapping = WS_ELEMENT_TYPE_MAPPING;
2108 break;
2110 default:
2111 FIXME( "unhandled field mapping %u\n", desc->mapping );
2112 return E_NOTIMPL;
2115 switch (desc->type)
2117 case WS_STRUCT_TYPE:
2118 hr = read_type_struct( reader, mapping, desc->typeDescription, heap, (void **)ptr );
2119 break;
2121 case WS_BOOL_TYPE:
2122 hr = read_type_bool( reader, mapping, desc->typeDescription, (BOOL *)ptr );
2123 break;
2125 case WS_INT8_TYPE:
2126 hr = read_type_int8( reader, mapping, desc->typeDescription, (INT8 *)ptr );
2127 break;
2129 case WS_INT16_TYPE:
2130 hr = read_type_int16( reader, mapping, desc->typeDescription, (INT16 *)ptr );
2131 break;
2133 case WS_INT32_TYPE:
2134 hr = read_type_int32( reader, mapping, desc->typeDescription, (INT32 *)ptr );
2135 break;
2137 case WS_INT64_TYPE:
2138 hr = read_type_int64( reader, mapping, desc->typeDescription, (INT64 *)ptr );
2139 break;
2141 case WS_UINT8_TYPE:
2142 hr = read_type_uint8( reader, mapping, desc->typeDescription, (UINT8 *)ptr );
2143 break;
2145 case WS_UINT16_TYPE:
2146 hr = read_type_uint16( reader, mapping, desc->typeDescription, (UINT16 *)ptr );
2147 break;
2149 case WS_UINT32_TYPE:
2150 hr = read_type_uint32( reader, mapping, desc->typeDescription, (UINT32 *)ptr );
2151 break;
2153 case WS_UINT64_TYPE:
2154 hr = read_type_uint64( reader, mapping, desc->typeDescription, (UINT64 *)ptr );
2155 break;
2157 case WS_WSZ_TYPE:
2158 hr = read_type_wsz( reader, mapping, desc->typeDescription, heap, (WCHAR **)ptr );
2159 break;
2161 default:
2162 FIXME( "type %u not implemented\n", desc->type );
2163 return E_NOTIMPL;
2166 return hr;
2169 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
2170 const WS_STRUCT_DESCRIPTION *desc, WS_HEAP *heap, void **ret )
2172 ULONG i;
2173 HRESULT hr;
2174 char *buf;
2176 if (!desc) return E_INVALIDARG;
2178 if (desc->structOptions)
2180 FIXME( "struct options 0x%x not supported\n", desc->structOptions );
2181 return E_NOTIMPL;
2184 switch (mapping)
2186 case WS_ELEMENT_TYPE_MAPPING:
2187 if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
2188 break;
2190 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2191 if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
2192 if ((hr = read_startelement( reader )) != S_OK) return hr;
2193 break;
2195 default:
2196 FIXME( "unhandled mapping %u\n", mapping );
2197 return E_NOTIMPL;
2200 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
2202 for (i = 0; i < desc->fieldCount; i++)
2204 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
2206 ws_free( heap, buf );
2207 return hr;
2211 switch (mapping)
2213 case WS_ELEMENT_TYPE_MAPPING:
2214 if ((hr = read_endelement( reader )) != S_OK) return hr;
2215 break;
2217 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2218 if ((hr = read_endelement( reader )) != S_OK) return hr;
2219 if ((hr = read_node( reader )) != S_OK) return hr;
2220 if (reader->state != READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2221 break;
2223 default: break;
2226 *ret = buf;
2227 return S_OK;
2230 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
2231 const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
2232 void *value, ULONG size )
2234 switch (type)
2236 case WS_STRUCT_TYPE:
2238 void **ptr = value;
2239 if (option != WS_READ_REQUIRED_POINTER || size != sizeof(*ptr))
2240 return E_INVALIDARG;
2242 return read_type_struct( reader, mapping, desc, heap, ptr );
2244 case WS_BOOL_TYPE:
2246 BOOL *ptr = value;
2247 if (option != WS_READ_REQUIRED_VALUE)
2249 FIXME( "read option %u not supported\n", option );
2250 return E_NOTIMPL;
2252 if (size != sizeof(*ptr)) return E_INVALIDARG;
2253 return read_type_bool( reader, mapping, desc, ptr );
2255 case WS_INT8_TYPE:
2257 INT8 *ptr = value;
2258 if (option != WS_READ_REQUIRED_VALUE)
2260 FIXME( "read option %u not supported\n", option );
2261 return E_NOTIMPL;
2263 if (size != sizeof(*ptr)) return E_INVALIDARG;
2264 return read_type_int8( reader, mapping, desc, ptr );
2266 case WS_INT16_TYPE:
2268 INT16 *ptr = value;
2269 if (option != WS_READ_REQUIRED_VALUE)
2271 FIXME( "read option %u not supported\n", option );
2272 return E_NOTIMPL;
2274 if (size != sizeof(*ptr)) return E_INVALIDARG;
2275 return read_type_int16( reader, mapping, desc, ptr );
2277 case WS_INT32_TYPE:
2279 INT32 *ptr = value;
2280 if (option != WS_READ_REQUIRED_VALUE)
2282 FIXME( "read option %u not supported\n", option );
2283 return E_NOTIMPL;
2285 if (size != sizeof(*ptr)) return E_INVALIDARG;
2286 return read_type_int32( reader, mapping, desc, ptr );
2288 case WS_INT64_TYPE:
2290 INT64 *ptr = value;
2291 if (option != WS_READ_REQUIRED_VALUE)
2293 FIXME( "read option %u not supported\n", option );
2294 return E_NOTIMPL;
2296 if (size != sizeof(*ptr)) return E_INVALIDARG;
2297 return read_type_int64( reader, mapping, desc, ptr );
2299 case WS_UINT8_TYPE:
2301 UINT8 *ptr = value;
2302 if (option != WS_READ_REQUIRED_VALUE)
2304 FIXME( "read option %u not supported\n", option );
2305 return E_NOTIMPL;
2307 if (size != sizeof(*ptr)) return E_INVALIDARG;
2308 return read_type_uint8( reader, mapping, desc, ptr );
2310 case WS_UINT16_TYPE:
2312 UINT16 *ptr = value;
2313 if (option != WS_READ_REQUIRED_VALUE)
2315 FIXME( "read option %u not supported\n", option );
2316 return E_NOTIMPL;
2318 if (size != sizeof(*ptr)) return E_INVALIDARG;
2319 return read_type_uint16( reader, mapping, desc, ptr );
2321 case WS_UINT32_TYPE:
2323 UINT32 *ptr = value;
2324 if (option != WS_READ_REQUIRED_VALUE)
2326 FIXME( "read option %u not supported\n", option );
2327 return E_NOTIMPL;
2329 if (size != sizeof(*ptr)) return E_INVALIDARG;
2330 return read_type_uint32( reader, mapping, desc, ptr );
2332 case WS_UINT64_TYPE:
2334 UINT64 *ptr = value;
2335 if (option != WS_READ_REQUIRED_VALUE)
2337 FIXME( "read option %u not supported\n", option );
2338 return E_NOTIMPL;
2340 if (size != sizeof(*ptr)) return E_INVALIDARG;
2341 return read_type_uint64( reader, mapping, desc, ptr );
2343 case WS_WSZ_TYPE:
2345 WCHAR **ptr = value;
2346 if (option != WS_READ_REQUIRED_POINTER)
2348 FIXME( "read option %u not supported\n", option );
2349 return E_NOTIMPL;
2351 if (size != sizeof(*ptr)) return E_INVALIDARG;
2352 return read_type_wsz( reader, mapping, desc, heap, ptr );
2354 default:
2355 FIXME( "type %u not supported\n", type );
2356 return E_NOTIMPL;
2360 /**************************************************************************
2361 * WsReadType [webservices.@]
2363 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
2364 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
2365 ULONG size, WS_ERROR *error )
2367 struct reader *reader = (struct reader *)handle;
2369 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
2370 size, error );
2371 if (error) FIXME( "ignoring error parameter\n" );
2373 if (!reader || !value) return E_INVALIDARG;
2375 return read_type( reader, mapping, type, desc, option, heap, value, size );
2378 /**************************************************************************
2379 * WsSetErrorProperty [webservices.@]
2381 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
2382 ULONG size )
2384 struct error *error = (struct error *)handle;
2386 TRACE( "%p %u %p %u\n", handle, id, value, size );
2388 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
2389 return set_error_prop( error, id, value, size );
2392 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
2394 static const char bom[] = {0xef,0xbb,0xbf};
2395 const unsigned char *p = data;
2397 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
2398 (size > 2 && !(*offset = 0));
2401 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
2403 static const char bom[] = {0xff,0xfe};
2404 const unsigned char *p = data;
2406 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
2407 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
2410 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
2412 WS_CHARSET ret = 0;
2414 /* FIXME: parse xml declaration */
2416 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
2417 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
2418 else
2420 FIXME( "charset not recognized\n" );
2421 return 0;
2424 TRACE( "detected charset %u\n", ret );
2425 return ret;
2428 static void set_input_buffer( struct reader *reader, const unsigned char *data, ULONG size )
2430 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
2431 reader->input_data = data;
2432 reader->input_size = size;
2434 reader->read_size = reader->input_size;
2435 reader->read_pos = 0;
2436 reader->read_bufptr = reader->input_data;
2439 /**************************************************************************
2440 * WsSetInput [webservices.@]
2442 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
2443 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
2444 ULONG count, WS_ERROR *error )
2446 struct reader *reader = (struct reader *)handle;
2447 struct node *node;
2448 HRESULT hr;
2449 ULONG i, offset = 0;
2451 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
2452 if (error) FIXME( "ignoring error parameter\n" );
2454 if (!reader) return E_INVALIDARG;
2456 for (i = 0; i < count; i++)
2458 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
2459 if (hr != S_OK) return hr;
2462 if ((hr = read_init_state( reader )) != S_OK) return hr;
2464 switch (encoding->encodingType)
2466 case WS_XML_READER_ENCODING_TYPE_TEXT:
2468 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
2469 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
2470 WS_CHARSET charset = text->charSet;
2472 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
2474 FIXME( "charset detection on input type %u not supported\n", input->inputType );
2475 return E_NOTIMPL;
2478 if (charset == WS_CHARSET_AUTO)
2479 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
2481 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
2482 if (hr != S_OK) return hr;
2483 break;
2485 default:
2486 FIXME( "encoding type %u not supported\n", encoding->encodingType );
2487 return E_NOTIMPL;
2489 switch (input->inputType)
2491 case WS_XML_READER_INPUT_TYPE_BUFFER:
2493 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
2494 set_input_buffer( reader, (const unsigned char *)buf->encodedData + offset, buf->encodedDataSize - offset );
2495 break;
2497 default:
2498 FIXME( "input type %u not supported\n", input->inputType );
2499 return E_NOTIMPL;
2502 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
2503 read_insert_bof( reader, node );
2504 return S_OK;
2507 /**************************************************************************
2508 * WsSetInputToBuffer [webservices.@]
2510 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
2511 const WS_XML_READER_PROPERTY *properties, ULONG count,
2512 WS_ERROR *error )
2514 struct reader *reader = (struct reader *)handle;
2515 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
2516 WS_CHARSET charset;
2517 struct node *node;
2518 HRESULT hr;
2519 ULONG i, offset = 0;
2521 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
2522 if (error) FIXME( "ignoring error parameter\n" );
2524 if (!reader || !xmlbuf) return E_INVALIDARG;
2526 for (i = 0; i < count; i++)
2528 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
2529 if (hr != S_OK) return hr;
2532 if ((hr = read_init_state( reader )) != S_OK) return hr;
2534 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
2535 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
2536 if (hr != S_OK) return hr;
2538 set_input_buffer( reader, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
2539 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
2540 read_insert_bof( reader, node );
2541 return S_OK;
2544 /**************************************************************************
2545 * WsXmlStringEquals [webservices.@]
2547 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
2549 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
2550 if (error) FIXME( "ignoring error parameter\n" );
2552 if (!str1 || !str2) return E_INVALIDARG;
2554 if (str1->length != str2->length) return S_FALSE;
2555 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
2556 return S_FALSE;