webservices: Implement WS_MOVE_TO_ROOT_ELEMENT in the reader.
[wine.git] / dlls / webservices / reader.c
blob87887ce3fde7a7124b38aef21f924f7edabcd6d5
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 HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
1349 struct list *ptr;
1350 BOOL success = FALSE;
1351 HRESULT hr = S_OK;
1353 if (!read_end_of_data( reader ))
1355 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
1356 if (hr != S_OK) return hr;
1358 switch (move)
1360 case WS_MOVE_TO_ROOT_ELEMENT:
1361 success = move_to_root_element( reader );
1362 break;
1364 case WS_MOVE_TO_FIRST_NODE:
1365 if ((ptr = list_head( &reader->current->parent->children )))
1367 reader->current = LIST_ENTRY( ptr, struct node, entry );
1368 success = TRUE;
1370 break;
1372 case WS_MOVE_TO_NEXT_NODE:
1373 if ((ptr = list_next( &reader->current->parent->children, &reader->current->entry )))
1375 reader->current = LIST_ENTRY( ptr, struct node, entry );
1376 success = TRUE;
1378 break;
1380 case WS_MOVE_TO_PREVIOUS_NODE:
1381 if ((ptr = list_prev( &reader->current->parent->children, &reader->current->entry )))
1383 reader->current = LIST_ENTRY( ptr, struct node, entry );
1384 success = TRUE;
1386 break;
1388 case WS_MOVE_TO_CHILD_NODE:
1389 if ((ptr = list_head( &reader->current->children )))
1391 reader->current = LIST_ENTRY( ptr, struct node, entry );
1392 success = TRUE;
1394 break;
1396 case WS_MOVE_TO_BOF:
1397 reader->current = reader->root;
1398 success = TRUE;
1399 break;
1401 case WS_MOVE_TO_EOF:
1402 if ((ptr = list_tail( &reader->root->children )))
1404 reader->current = LIST_ENTRY( ptr, struct node, entry );
1405 success = TRUE;
1407 break;
1409 default:
1410 FIXME( "unhandled move %u\n", move );
1411 return E_NOTIMPL;
1414 if (found)
1416 *found = success;
1417 return S_OK;
1419 return success ? S_OK : WS_E_INVALID_FORMAT;
1422 /**************************************************************************
1423 * WsMoveReader [webservices.@]
1425 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
1427 struct reader *reader = (struct reader *)handle;
1429 TRACE( "%p %u %p %p\n", handle, move, found, error );
1430 if (error) FIXME( "ignoring error parameter\n" );
1432 if (!reader) return E_INVALIDARG;
1433 if (!reader->input_type) return WS_E_INVALID_OPERATION;
1435 return read_move_to( reader, move, found );
1438 /**************************************************************************
1439 * WsReadStartAttribute [webservices.@]
1441 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
1443 struct reader *reader = (struct reader *)handle;
1444 WS_XML_ELEMENT_NODE *elem;
1446 TRACE( "%p %u %p\n", handle, index, error );
1447 if (error) FIXME( "ignoring error parameter\n" );
1449 if (!reader) return E_INVALIDARG;
1451 elem = &reader->current->hdr;
1452 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
1453 return WS_E_INVALID_FORMAT;
1455 reader->current_attr = index;
1456 reader->state = READER_STATE_STARTATTRIBUTE;
1457 return S_OK;
1460 /**************************************************************************
1461 * WsReadEndAttribute [webservices.@]
1463 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
1465 struct reader *reader = (struct reader *)handle;
1467 TRACE( "%p %p\n", handle, error );
1468 if (error) FIXME( "ignoring error parameter\n" );
1470 if (!reader) return E_INVALIDARG;
1472 if (reader->state != READER_STATE_STARTATTRIBUTE)
1473 return WS_E_INVALID_FORMAT;
1475 reader->state = READER_STATE_STARTELEMENT;
1476 return S_OK;
1479 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
1481 WCHAR *ret;
1483 switch (text->textType)
1485 case WS_XML_TEXT_TYPE_UTF8:
1487 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
1488 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
1489 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
1490 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
1491 ret[len] = 0;
1492 break;
1494 default:
1495 FIXME( "unhandled type %u\n", text->textType );
1496 return NULL;
1499 return ret;
1502 #define MAX_INT8 0x7f
1503 #define MIN_INT8 (-MAX_INT8 - 1)
1504 #define MAX_INT16 0x7fff
1505 #define MIN_INT16 (-MAX_INT16 - 1)
1506 #define MAX_INT32 0x7fffffff
1507 #define MIN_INT32 (-MAX_INT32 - 1)
1508 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1509 #define MIN_INT64 (-MAX_INT64 - 1)
1510 #define MAX_UINT8 0xff
1511 #define MAX_UINT16 0xffff
1512 #define MAX_UINT32 0xffffffff
1513 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1515 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
1517 BOOL negative = FALSE;
1518 const unsigned char *ptr = str;
1520 *ret = 0;
1521 while (len && read_isspace( *ptr )) { ptr++; len--; }
1522 while (len && read_isspace( ptr[len - 1] )) { len--; }
1523 if (!len) return WS_E_INVALID_FORMAT;
1525 if (*ptr == '-')
1527 negative = TRUE;
1528 ptr++;
1529 len--;
1531 if (!len) return WS_E_INVALID_FORMAT;
1533 while (len--)
1535 int val;
1537 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1538 val = *ptr - '0';
1539 if (negative) val = -val;
1541 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
1542 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
1544 return WS_E_NUMERIC_OVERFLOW;
1546 *ret = *ret * 10 + val;
1547 ptr++;
1550 return S_OK;
1553 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
1555 const unsigned char *ptr = str;
1557 *ret = 0;
1558 while (len && read_isspace( *ptr )) { ptr++; len--; }
1559 while (len && read_isspace( ptr[len - 1] )) { len--; }
1560 if (!len) return WS_E_INVALID_FORMAT;
1562 while (len--)
1564 unsigned int val;
1566 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1567 val = *ptr - '0';
1569 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
1570 *ret = *ret * 10 + val;
1571 ptr++;
1574 return S_OK;
1577 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
1579 WS_XML_TEXT_NODE *text;
1581 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_TEXT)
1582 return WS_E_INVALID_FORMAT;
1584 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
1585 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
1587 FIXME( "text type %u not supported\n", text->text->textType );
1588 return E_NOTIMPL;
1590 *ret = (WS_XML_UTF8_TEXT *)text->text;
1591 return S_OK;
1594 static HRESULT read_get_attribute_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
1596 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1597 WS_XML_ATTRIBUTE *attr;
1599 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT ||
1600 reader->current_attr >= elem->attributeCount) return WS_E_INVALID_FORMAT;
1602 attr = elem->attributes[reader->current_attr];
1603 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
1605 FIXME( "text type %u not supported\n", attr->value->textType );
1606 return E_NOTIMPL;
1608 *ret = (WS_XML_UTF8_TEXT *)attr->value;
1609 reader->current_attr++;
1610 return S_OK;
1613 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
1614 const WS_XML_STRING *ns, ULONG *index )
1616 ULONG i;
1617 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
1619 if (!localname)
1621 *index = reader->current_attr;
1622 return TRUE;
1624 for (i = 0; i < elem->attributeCount; i++)
1626 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
1627 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
1629 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
1630 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
1632 *index = i;
1633 return TRUE;
1636 return FALSE;
1639 /**************************************************************************
1640 * WsFindAttribute [webservices.@]
1642 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
1643 const WS_XML_STRING *ns, BOOL required, ULONG *index,
1644 WS_ERROR *error )
1646 struct reader *reader = (struct reader *)handle;
1648 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
1649 required, index, error );
1650 if (error) FIXME( "ignoring error parameter\n" );
1652 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
1654 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT)
1655 return WS_E_INVALID_OPERATION;
1657 if (!find_attribute( reader, localname, ns, index ))
1659 if (required) return WS_E_INVALID_FORMAT;
1660 *index = ~0u;
1661 return S_FALSE;
1663 return S_OK;
1666 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
1667 const WS_BOOL_DESCRIPTION *desc, BOOL *ret )
1669 WS_XML_UTF8_TEXT *utf8;
1670 HRESULT hr;
1671 ULONG len;
1673 if (desc)
1675 FIXME( "description not supported\n" );
1676 return E_NOTIMPL;
1678 switch (mapping)
1680 case WS_ATTRIBUTE_TYPE_MAPPING:
1681 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1682 len = utf8->value.length;
1683 break;
1685 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1686 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1687 len = utf8->value.length;
1688 break;
1690 default:
1691 FIXME( "mapping %u not supported\n", mapping );
1692 return E_NOTIMPL;
1695 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) *ret = TRUE;
1696 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) *ret = TRUE;
1697 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) *ret = FALSE;
1698 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) *ret = FALSE;
1699 else return WS_E_INVALID_FORMAT;
1701 return S_OK;
1704 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
1705 const WS_INT8_DESCRIPTION *desc, INT8 *ret )
1707 WS_XML_UTF8_TEXT *utf8;
1708 HRESULT hr;
1709 INT64 val;
1711 if (desc)
1713 FIXME( "description not supported\n" );
1714 return E_NOTIMPL;
1716 switch (mapping)
1718 case WS_ATTRIBUTE_TYPE_MAPPING:
1719 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1720 break;
1722 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1723 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1724 break;
1726 default:
1727 FIXME( "mapping %u not supported\n", mapping );
1728 return E_NOTIMPL;
1731 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
1732 return hr;
1734 *ret = val;
1735 return S_OK;
1738 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
1739 const WS_INT16_DESCRIPTION *desc, INT16 *ret )
1741 WS_XML_UTF8_TEXT *utf8;
1742 HRESULT hr;
1743 INT64 val;
1745 if (desc)
1747 FIXME( "description not supported\n" );
1748 return E_NOTIMPL;
1750 switch (mapping)
1752 case WS_ATTRIBUTE_TYPE_MAPPING:
1753 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1754 break;
1756 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1757 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1758 break;
1760 default:
1761 FIXME( "mapping %u not supported\n", mapping );
1762 return E_NOTIMPL;
1765 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
1766 return hr;
1768 *ret = val;
1769 return S_OK;
1772 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
1773 const WS_INT32_DESCRIPTION *desc, INT32 *ret )
1775 WS_XML_UTF8_TEXT *utf8;
1776 HRESULT hr;
1777 INT64 val;
1779 if (desc)
1781 FIXME( "description not supported\n" );
1782 return E_NOTIMPL;
1784 switch (mapping)
1786 case WS_ATTRIBUTE_TYPE_MAPPING:
1787 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1788 break;
1790 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1791 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1792 break;
1794 default:
1795 FIXME( "mapping %u not supported\n", mapping );
1796 return E_NOTIMPL;
1799 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
1800 return hr;
1802 *ret = val;
1803 return S_OK;
1806 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
1807 const WS_INT64_DESCRIPTION *desc, INT64 *ret )
1809 WS_XML_UTF8_TEXT *utf8;
1810 HRESULT hr;
1811 INT64 val;
1813 if (desc)
1815 FIXME( "description not supported\n" );
1816 return E_NOTIMPL;
1818 switch (mapping)
1820 case WS_ATTRIBUTE_TYPE_MAPPING:
1821 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1822 break;
1824 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1825 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1826 break;
1828 default:
1829 FIXME( "mapping %u not supported\n", mapping );
1830 return E_NOTIMPL;
1833 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
1834 return hr;
1836 *ret = val;
1837 return S_OK;
1840 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
1841 const WS_UINT8_DESCRIPTION *desc, UINT8 *ret )
1843 WS_XML_UTF8_TEXT *utf8;
1844 HRESULT hr;
1845 UINT64 val;
1847 if (desc)
1849 FIXME( "description not supported\n" );
1850 return E_NOTIMPL;
1852 switch (mapping)
1854 case WS_ATTRIBUTE_TYPE_MAPPING:
1855 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1856 break;
1858 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1859 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1860 break;
1862 default:
1863 FIXME( "mapping %u not supported\n", mapping );
1864 return E_NOTIMPL;
1867 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
1868 return hr;
1870 *ret = val;
1871 return S_OK;
1874 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
1875 const WS_UINT16_DESCRIPTION *desc, UINT16 *ret )
1877 WS_XML_UTF8_TEXT *utf8;
1878 HRESULT hr;
1879 UINT64 val;
1881 if (desc)
1883 FIXME( "description not supported\n" );
1884 return E_NOTIMPL;
1886 switch (mapping)
1888 case WS_ATTRIBUTE_TYPE_MAPPING:
1889 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1890 break;
1892 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1893 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1894 break;
1896 default:
1897 FIXME( "mapping %u not supported\n", mapping );
1898 return E_NOTIMPL;
1901 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
1902 return hr;
1904 *ret = val;
1905 return S_OK;
1908 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
1909 const WS_UINT32_DESCRIPTION *desc, UINT32 *ret )
1911 WS_XML_UTF8_TEXT *utf8;
1912 HRESULT hr;
1913 UINT64 val;
1915 if (desc)
1917 FIXME( "description not supported\n" );
1918 return E_NOTIMPL;
1920 switch (mapping)
1922 case WS_ATTRIBUTE_TYPE_MAPPING:
1923 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1924 break;
1926 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1927 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1928 break;
1930 default:
1931 FIXME( "mapping %u not supported\n", mapping );
1932 return E_NOTIMPL;
1935 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
1936 return hr;
1938 *ret = val;
1939 return S_OK;
1942 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
1943 const WS_UINT64_DESCRIPTION *desc, UINT64 *ret )
1945 WS_XML_UTF8_TEXT *utf8;
1946 HRESULT hr;
1947 UINT64 val;
1949 if (desc)
1951 FIXME( "description not supported\n" );
1952 return E_NOTIMPL;
1954 switch (mapping)
1956 case WS_ATTRIBUTE_TYPE_MAPPING:
1957 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1958 break;
1960 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1961 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1962 break;
1964 default:
1965 FIXME( "mapping %u not supported\n", mapping );
1966 return E_NOTIMPL;
1969 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
1970 return hr;
1972 *ret = val;
1973 return S_OK;
1976 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
1977 const WS_WSZ_DESCRIPTION *desc, WS_HEAP *heap, WCHAR **ret )
1979 WS_XML_UTF8_TEXT *utf8;
1980 HRESULT hr;
1981 WCHAR *str;
1983 if (desc)
1985 FIXME( "description not supported\n" );
1986 return E_NOTIMPL;
1988 switch (mapping)
1990 case WS_ATTRIBUTE_TYPE_MAPPING:
1991 if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
1992 break;
1994 case WS_ELEMENT_TYPE_MAPPING:
1995 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1996 if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
1997 break;
1999 default:
2000 FIXME( "mapping %u not supported\n", mapping );
2001 return E_NOTIMPL;
2004 if (!(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
2005 *ret = str;
2006 return S_OK;
2009 static HRESULT read_type_struct( struct reader *, WS_TYPE_MAPPING, const WS_STRUCT_DESCRIPTION *,
2010 WS_HEAP *, void ** );
2012 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
2013 WS_HEAP *heap, char *buf )
2015 char *ptr = buf + desc->offset;
2016 WS_TYPE_MAPPING mapping;
2017 HRESULT hr;
2019 if (desc->options && desc->options != WS_FIELD_POINTER &&
2020 desc->options != WS_FIELD_OPTIONAL &&
2021 desc->options != (WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
2023 FIXME( "options 0x%x not supported\n", desc->options );
2024 return E_NOTIMPL;
2027 switch (desc->mapping)
2029 case WS_ATTRIBUTE_FIELD_MAPPING:
2030 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
2031 break;
2033 case WS_ELEMENT_FIELD_MAPPING:
2034 mapping = WS_ELEMENT_TYPE_MAPPING;
2035 break;
2037 default:
2038 FIXME( "unhandled field mapping %u\n", desc->mapping );
2039 return E_NOTIMPL;
2042 switch (desc->type)
2044 case WS_STRUCT_TYPE:
2045 hr = read_type_struct( reader, mapping, desc->typeDescription, heap, (void **)ptr );
2046 break;
2048 case WS_BOOL_TYPE:
2049 hr = read_type_bool( reader, mapping, desc->typeDescription, (BOOL *)ptr );
2050 break;
2052 case WS_INT8_TYPE:
2053 hr = read_type_int8( reader, mapping, desc->typeDescription, (INT8 *)ptr );
2054 break;
2056 case WS_INT16_TYPE:
2057 hr = read_type_int16( reader, mapping, desc->typeDescription, (INT16 *)ptr );
2058 break;
2060 case WS_INT32_TYPE:
2061 hr = read_type_int32( reader, mapping, desc->typeDescription, (INT32 *)ptr );
2062 break;
2064 case WS_INT64_TYPE:
2065 hr = read_type_int64( reader, mapping, desc->typeDescription, (INT64 *)ptr );
2066 break;
2068 case WS_UINT8_TYPE:
2069 hr = read_type_uint8( reader, mapping, desc->typeDescription, (UINT8 *)ptr );
2070 break;
2072 case WS_UINT16_TYPE:
2073 hr = read_type_uint16( reader, mapping, desc->typeDescription, (UINT16 *)ptr );
2074 break;
2076 case WS_UINT32_TYPE:
2077 hr = read_type_uint32( reader, mapping, desc->typeDescription, (UINT32 *)ptr );
2078 break;
2080 case WS_UINT64_TYPE:
2081 hr = read_type_uint64( reader, mapping, desc->typeDescription, (UINT64 *)ptr );
2082 break;
2084 case WS_WSZ_TYPE:
2085 hr = read_type_wsz( reader, mapping, desc->typeDescription, heap, (WCHAR **)ptr );
2086 break;
2088 default:
2089 FIXME( "type %u not implemented\n", desc->type );
2090 return E_NOTIMPL;
2093 return hr;
2096 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
2097 const WS_STRUCT_DESCRIPTION *desc, WS_HEAP *heap, void **ret )
2099 ULONG i;
2100 HRESULT hr;
2101 char *buf;
2103 if (!desc) return E_INVALIDARG;
2105 if (desc->structOptions)
2107 FIXME( "struct options 0x%x not supported\n", desc->structOptions );
2108 return E_NOTIMPL;
2111 switch (mapping)
2113 case WS_ELEMENT_TYPE_MAPPING:
2114 if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
2115 break;
2117 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2118 if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
2119 if ((hr = read_startelement( reader )) != S_OK) return hr;
2120 break;
2122 default:
2123 FIXME( "unhandled mapping %u\n", mapping );
2124 return E_NOTIMPL;
2127 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
2129 for (i = 0; i < desc->fieldCount; i++)
2131 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
2133 ws_free( heap, buf );
2134 return hr;
2138 switch (mapping)
2140 case WS_ELEMENT_TYPE_MAPPING:
2141 if ((hr = read_endelement( reader )) != S_OK) return hr;
2142 break;
2144 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2145 if ((hr = read_endelement( reader )) != S_OK) return hr;
2146 if ((hr = read_node( reader )) != S_OK) return hr;
2147 if (reader->state != READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2148 break;
2150 default: break;
2153 *ret = buf;
2154 return S_OK;
2157 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
2158 const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
2159 void *value, ULONG size )
2161 switch (type)
2163 case WS_STRUCT_TYPE:
2165 void **ptr = value;
2166 if (option != WS_READ_REQUIRED_POINTER || size != sizeof(*ptr))
2167 return E_INVALIDARG;
2169 return read_type_struct( reader, mapping, desc, heap, ptr );
2171 case WS_BOOL_TYPE:
2173 BOOL *ptr = value;
2174 if (option != WS_READ_REQUIRED_VALUE)
2176 FIXME( "read option %u not supported\n", option );
2177 return E_NOTIMPL;
2179 if (size != sizeof(*ptr)) return E_INVALIDARG;
2180 return read_type_bool( reader, mapping, desc, ptr );
2182 case WS_INT8_TYPE:
2184 INT8 *ptr = value;
2185 if (option != WS_READ_REQUIRED_VALUE)
2187 FIXME( "read option %u not supported\n", option );
2188 return E_NOTIMPL;
2190 if (size != sizeof(*ptr)) return E_INVALIDARG;
2191 return read_type_int8( reader, mapping, desc, ptr );
2193 case WS_INT16_TYPE:
2195 INT16 *ptr = value;
2196 if (option != WS_READ_REQUIRED_VALUE)
2198 FIXME( "read option %u not supported\n", option );
2199 return E_NOTIMPL;
2201 if (size != sizeof(*ptr)) return E_INVALIDARG;
2202 return read_type_int16( reader, mapping, desc, ptr );
2204 case WS_INT32_TYPE:
2206 INT32 *ptr = value;
2207 if (option != WS_READ_REQUIRED_VALUE)
2209 FIXME( "read option %u not supported\n", option );
2210 return E_NOTIMPL;
2212 if (size != sizeof(*ptr)) return E_INVALIDARG;
2213 return read_type_int32( reader, mapping, desc, ptr );
2215 case WS_INT64_TYPE:
2217 INT64 *ptr = value;
2218 if (option != WS_READ_REQUIRED_VALUE)
2220 FIXME( "read option %u not supported\n", option );
2221 return E_NOTIMPL;
2223 if (size != sizeof(*ptr)) return E_INVALIDARG;
2224 return read_type_int64( reader, mapping, desc, ptr );
2226 case WS_UINT8_TYPE:
2228 UINT8 *ptr = value;
2229 if (option != WS_READ_REQUIRED_VALUE)
2231 FIXME( "read option %u not supported\n", option );
2232 return E_NOTIMPL;
2234 if (size != sizeof(*ptr)) return E_INVALIDARG;
2235 return read_type_uint8( reader, mapping, desc, ptr );
2237 case WS_UINT16_TYPE:
2239 UINT16 *ptr = value;
2240 if (option != WS_READ_REQUIRED_VALUE)
2242 FIXME( "read option %u not supported\n", option );
2243 return E_NOTIMPL;
2245 if (size != sizeof(*ptr)) return E_INVALIDARG;
2246 return read_type_uint16( reader, mapping, desc, ptr );
2248 case WS_UINT32_TYPE:
2250 UINT32 *ptr = value;
2251 if (option != WS_READ_REQUIRED_VALUE)
2253 FIXME( "read option %u not supported\n", option );
2254 return E_NOTIMPL;
2256 if (size != sizeof(*ptr)) return E_INVALIDARG;
2257 return read_type_uint32( reader, mapping, desc, ptr );
2259 case WS_UINT64_TYPE:
2261 UINT64 *ptr = value;
2262 if (option != WS_READ_REQUIRED_VALUE)
2264 FIXME( "read option %u not supported\n", option );
2265 return E_NOTIMPL;
2267 if (size != sizeof(*ptr)) return E_INVALIDARG;
2268 return read_type_uint64( reader, mapping, desc, ptr );
2270 case WS_WSZ_TYPE:
2272 WCHAR **ptr = value;
2273 if (option != WS_READ_REQUIRED_POINTER)
2275 FIXME( "read option %u not supported\n", option );
2276 return E_NOTIMPL;
2278 if (size != sizeof(*ptr)) return E_INVALIDARG;
2279 return read_type_wsz( reader, mapping, desc, heap, ptr );
2281 default:
2282 FIXME( "type %u not supported\n", type );
2283 return E_NOTIMPL;
2287 /**************************************************************************
2288 * WsReadType [webservices.@]
2290 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
2291 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
2292 ULONG size, WS_ERROR *error )
2294 struct reader *reader = (struct reader *)handle;
2296 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
2297 size, error );
2298 if (error) FIXME( "ignoring error parameter\n" );
2300 if (!reader || !value) return E_INVALIDARG;
2302 return read_type( reader, mapping, type, desc, option, heap, value, size );
2305 /**************************************************************************
2306 * WsSetErrorProperty [webservices.@]
2308 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
2309 ULONG size )
2311 struct error *error = (struct error *)handle;
2313 TRACE( "%p %u %p %u\n", handle, id, value, size );
2315 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
2316 return set_error_prop( error, id, value, size );
2319 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
2321 static const char bom[] = {0xef,0xbb,0xbf};
2322 const unsigned char *p = data;
2324 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
2325 (size > 2 && !(*offset = 0));
2328 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
2330 static const char bom[] = {0xff,0xfe};
2331 const unsigned char *p = data;
2333 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
2334 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
2337 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
2339 WS_CHARSET ret = 0;
2341 /* FIXME: parse xml declaration */
2343 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
2344 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
2345 else
2347 FIXME( "charset not recognized\n" );
2348 return 0;
2351 TRACE( "detected charset %u\n", ret );
2352 return ret;
2355 static void set_input_buffer( struct reader *reader, const unsigned char *data, ULONG size )
2357 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
2358 reader->input_data = data;
2359 reader->input_size = size;
2361 reader->read_size = reader->input_size;
2362 reader->read_pos = 0;
2363 reader->read_bufptr = reader->input_data;
2366 /**************************************************************************
2367 * WsSetInput [webservices.@]
2369 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
2370 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
2371 ULONG count, WS_ERROR *error )
2373 struct reader *reader = (struct reader *)handle;
2374 struct node *node;
2375 HRESULT hr;
2376 ULONG i, offset = 0;
2378 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
2379 if (error) FIXME( "ignoring error parameter\n" );
2381 if (!reader) return E_INVALIDARG;
2383 for (i = 0; i < count; i++)
2385 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
2386 if (hr != S_OK) return hr;
2389 if ((hr = read_init_state( reader )) != S_OK) return hr;
2391 switch (encoding->encodingType)
2393 case WS_XML_READER_ENCODING_TYPE_TEXT:
2395 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
2396 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
2397 WS_CHARSET charset = text->charSet;
2399 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
2401 FIXME( "charset detection on input type %u not supported\n", input->inputType );
2402 return E_NOTIMPL;
2405 if (charset == WS_CHARSET_AUTO)
2406 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
2408 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
2409 if (hr != S_OK) return hr;
2410 break;
2412 default:
2413 FIXME( "encoding type %u not supported\n", encoding->encodingType );
2414 return E_NOTIMPL;
2416 switch (input->inputType)
2418 case WS_XML_READER_INPUT_TYPE_BUFFER:
2420 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
2421 set_input_buffer( reader, (const unsigned char *)buf->encodedData + offset, buf->encodedDataSize - offset );
2422 break;
2424 default:
2425 FIXME( "input type %u not supported\n", input->inputType );
2426 return E_NOTIMPL;
2429 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
2430 read_insert_bof( reader, node );
2431 return S_OK;
2434 /**************************************************************************
2435 * WsSetInputToBuffer [webservices.@]
2437 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
2438 const WS_XML_READER_PROPERTY *properties, ULONG count,
2439 WS_ERROR *error )
2441 struct reader *reader = (struct reader *)handle;
2442 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
2443 WS_CHARSET charset;
2444 struct node *node;
2445 HRESULT hr;
2446 ULONG i, offset = 0;
2448 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
2449 if (error) FIXME( "ignoring error parameter\n" );
2451 if (!reader || !xmlbuf) return E_INVALIDARG;
2453 for (i = 0; i < count; i++)
2455 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
2456 if (hr != S_OK) return hr;
2459 if ((hr = read_init_state( reader )) != S_OK) return hr;
2461 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
2462 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
2463 if (hr != S_OK) return hr;
2465 set_input_buffer( reader, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
2466 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
2467 read_insert_bof( reader, node );
2468 return S_OK;
2471 /**************************************************************************
2472 * WsXmlStringEquals [webservices.@]
2474 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
2476 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
2477 if (error) FIXME( "ignoring error parameter\n" );
2479 if (!str1 || !str2) return E_INVALIDARG;
2481 if (str1->length != str2->length) return S_FALSE;
2482 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
2483 return S_FALSE;