webservices: Implement WsWriteStartAttribute.
[wine/multimedia.git] / dlls / webservices / reader.c
blobcc71f982bd231db4928ba439c424344d9aeea184
1 /*
2 * Copyright 2015 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 void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
169 struct heap *heap = (struct heap *)handle;
170 return HeapReAlloc( heap->handle, 0, ptr, size );
173 void ws_free( WS_HEAP *handle, void *ptr )
175 struct heap *heap = (struct heap *)handle;
176 HeapFree( heap->handle, 0, ptr );
179 /**************************************************************************
180 * WsAlloc [webservices.@]
182 HRESULT WINAPI WsAlloc( WS_HEAP *handle, SIZE_T size, void **ptr, WS_ERROR *error )
184 void *mem;
186 TRACE( "%p %u %p %p\n", handle, (ULONG)size, ptr, error );
187 if (error) FIXME( "ignoring error parameter\n" );
189 if (!handle || !ptr) return E_INVALIDARG;
191 if (!(mem = ws_alloc( handle, size ))) return E_OUTOFMEMORY;
192 *ptr = mem;
193 return S_OK;
196 static struct heap *alloc_heap(void)
198 static const ULONG count = sizeof(heap_props)/sizeof(heap_props[0]);
199 struct heap *ret;
200 ULONG i, size = sizeof(*ret) + count * sizeof(WS_HEAP_PROPERTY);
201 char *ptr;
203 for (i = 0; i < count; i++) size += heap_props[i].size;
204 if (!(ret = heap_alloc_zero( size ))) return NULL;
206 ptr = (char *)&ret->prop[count];
207 for (i = 0; i < count; i++)
209 ret->prop[i].value = ptr;
210 ret->prop[i].valueSize = heap_props[i].size;
211 ptr += ret->prop[i].valueSize;
213 ret->prop_count = count;
214 return ret;
217 static HRESULT set_heap_prop( struct heap *heap, WS_HEAP_PROPERTY_ID id, const void *value, ULONG size )
219 if (id >= heap->prop_count || size != heap_props[id].size || heap_props[id].readonly)
220 return E_INVALIDARG;
222 memcpy( heap->prop[id].value, value, size );
223 return S_OK;
226 static HRESULT get_heap_prop( struct heap *heap, WS_HEAP_PROPERTY_ID id, void *buf, ULONG size )
228 if (id >= heap->prop_count || size != heap_props[id].size)
229 return E_INVALIDARG;
231 memcpy( buf, heap->prop[id].value, heap->prop[id].valueSize );
232 return S_OK;
235 /**************************************************************************
236 * WsCreateHeap [webservices.@]
238 HRESULT WINAPI WsCreateHeap( SIZE_T max_size, SIZE_T trim_size, const WS_HEAP_PROPERTY *properties,
239 ULONG count, WS_HEAP **handle, WS_ERROR *error )
241 struct heap *heap;
243 TRACE( "%u %u %p %u %p %p\n", (ULONG)max_size, (ULONG)trim_size, properties, count, handle, error );
244 if (error) FIXME( "ignoring error parameter\n" );
246 if (!handle || count) return E_INVALIDARG;
247 if (!(heap = alloc_heap())) return E_OUTOFMEMORY;
249 set_heap_prop( heap, WS_HEAP_PROPERTY_MAX_SIZE, &max_size, sizeof(max_size) );
250 set_heap_prop( heap, WS_HEAP_PROPERTY_TRIM_SIZE, &trim_size, sizeof(trim_size) );
252 if (!(heap->handle = HeapCreate( 0, 0, max_size )))
254 heap_free( heap );
255 return E_OUTOFMEMORY;
258 *handle = (WS_HEAP *)heap;
259 return S_OK;
262 /**************************************************************************
263 * WsFreeHeap [webservices.@]
265 void WINAPI WsFreeHeap( WS_HEAP *handle )
267 struct heap *heap = (struct heap *)handle;
269 TRACE( "%p\n", handle );
271 if (!heap) return;
272 HeapDestroy( heap->handle );
273 heap_free( heap );
276 struct node *alloc_node( WS_XML_NODE_TYPE type )
278 struct node *ret;
280 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
281 ret->hdr.node.nodeType = type;
282 list_init( &ret->entry );
283 list_init( &ret->children );
284 return ret;
287 void free_attribute( WS_XML_ATTRIBUTE *attr )
289 if (!attr) return;
290 heap_free( attr->prefix );
291 heap_free( attr->localName );
292 heap_free( attr->ns );
293 heap_free( attr->value );
294 heap_free( attr );
297 void free_node( struct node *node )
299 if (!node) return;
300 switch (node->hdr.node.nodeType)
302 case WS_XML_NODE_TYPE_ELEMENT:
304 WS_XML_ELEMENT_NODE *elem = (WS_XML_ELEMENT_NODE *)node;
305 ULONG i;
307 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
308 heap_free( elem->attributes );
309 heap_free( elem->prefix );
310 heap_free( elem->localName );
311 heap_free( elem->ns );
312 break;
314 case WS_XML_NODE_TYPE_TEXT:
316 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
317 heap_free( text->text );
318 break;
320 case WS_XML_NODE_TYPE_COMMENT:
322 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
323 heap_free( comment->value.bytes );
325 case WS_XML_NODE_TYPE_END_ELEMENT:
326 case WS_XML_NODE_TYPE_EOF:
327 case WS_XML_NODE_TYPE_BOF:
328 break;
330 default:
331 ERR( "unhandled type %u\n", node->hdr.node.nodeType );
332 break;
334 heap_free( node );
337 void destroy_nodes( struct node *node )
339 struct list *ptr;
341 if (!node) return;
342 while ((ptr = list_head( &node->children )))
344 struct node *child = LIST_ENTRY( ptr, struct node, entry );
345 list_remove( &child->entry );
346 destroy_nodes( child );
348 free_node( node );
351 static const struct
353 ULONG size;
354 BOOL readonly;
356 reader_props[] =
358 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
359 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
360 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
361 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
362 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
363 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
364 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
365 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
366 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
367 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
368 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
369 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
370 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
371 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
372 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
375 enum reader_state
377 READER_STATE_INITIAL,
378 READER_STATE_BOF,
379 READER_STATE_STARTELEMENT,
380 READER_STATE_STARTENDELEMENT,
381 READER_STATE_TEXT,
382 READER_STATE_ENDELEMENT,
383 READER_STATE_COMMENT,
384 READER_STATE_EOF
387 struct reader
389 ULONG read_size;
390 ULONG read_pos;
391 const char *read_bufptr;
392 enum reader_state state;
393 struct node *root;
394 struct node *current;
395 WS_XML_READER_INPUT_TYPE input_type;
396 const char *input_data;
397 ULONG input_size;
398 ULONG prop_count;
399 WS_XML_READER_PROPERTY prop[sizeof(reader_props)/sizeof(reader_props[0])];
402 static struct reader *alloc_reader(void)
404 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
405 struct reader *ret;
406 ULONG i, size = sizeof(*ret) + count * sizeof(WS_XML_READER_PROPERTY);
407 char *ptr;
409 for (i = 0; i < count; i++) size += reader_props[i].size;
410 if (!(ret = heap_alloc_zero( size ))) return NULL;
412 ptr = (char *)&ret->prop[count];
413 for (i = 0; i < count; i++)
415 ret->prop[i].value = ptr;
416 ret->prop[i].valueSize = reader_props[i].size;
417 ptr += ret->prop[i].valueSize;
419 ret->prop_count = count;
420 return ret;
423 static HRESULT set_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID id, const void *value, ULONG size )
425 if (id >= reader->prop_count || size != reader_props[id].size || reader_props[id].readonly)
426 return E_INVALIDARG;
428 memcpy( reader->prop[id].value, value, size );
429 return S_OK;
432 static HRESULT get_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID id, void *buf, ULONG size )
434 if (id >= reader->prop_count || size != reader_props[id].size)
435 return E_INVALIDARG;
437 memcpy( buf, reader->prop[id].value, reader->prop[id].valueSize );
438 return S_OK;
441 static void read_insert_eof( struct reader *reader, struct node *eof )
443 if (!reader->root) reader->root = eof;
444 else
446 eof->parent = reader->root;
447 list_add_tail( &reader->root->children, &eof->entry );
449 reader->current = eof;
452 static void read_insert_bof( struct reader *reader, struct node *bof )
454 reader->root->parent = bof;
455 list_add_tail( &bof->children, &reader->root->entry );
456 reader->current = reader->root = bof;
459 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
461 node->parent = parent;
462 if (node->parent == reader->root)
464 struct list *eof = list_tail( &reader->root->children );
465 list_add_before( eof, &node->entry );
467 else list_add_tail( &parent->children, &node->entry );
468 reader->current = node;
471 static HRESULT read_init_state( struct reader *reader )
473 struct node *node;
475 destroy_nodes( reader->root );
476 reader->root = NULL;
477 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
478 read_insert_eof( reader, node );
479 reader->state = READER_STATE_INITIAL;
480 return S_OK;
483 /**************************************************************************
484 * WsCreateReader [webservices.@]
486 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
487 WS_XML_READER **handle, WS_ERROR *error )
489 struct reader *reader;
490 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
491 WS_CHARSET charset = WS_CHARSET_UTF8;
492 BOOL read_decl = TRUE;
493 HRESULT hr;
495 TRACE( "%p %u %p %p\n", properties, count, handle, error );
496 if (error) FIXME( "ignoring error parameter\n" );
498 if (!handle) return E_INVALIDARG;
499 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
501 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
502 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
503 set_reader_prop( reader, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
504 set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
505 set_reader_prop( reader, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
507 for (i = 0; i < count; i++)
509 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
510 if (hr != S_OK)
512 heap_free( reader );
513 return hr;
517 if ((hr = read_init_state( reader )) != S_OK)
519 heap_free( reader );
520 return hr;
523 *handle = (WS_XML_READER *)reader;
524 return S_OK;
527 /**************************************************************************
528 * WsFreeReader [webservices.@]
530 void WINAPI WsFreeReader( WS_XML_READER *handle )
532 struct reader *reader = (struct reader *)handle;
534 TRACE( "%p\n", handle );
536 if (!reader) return;
537 destroy_nodes( reader->root );
538 heap_free( reader );
541 /**************************************************************************
542 * WsFillReader [webservices.@]
544 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
545 WS_ERROR *error )
547 struct reader *reader = (struct reader *)handle;
549 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
550 if (error) FIXME( "ignoring error parameter\n" );
552 if (!reader) return E_INVALIDARG;
554 /* FIXME: add support for stream input */
555 reader->read_size = min( min_size, reader->input_size );
556 reader->read_pos = 0;
558 return S_OK;
561 /**************************************************************************
562 * WsGetErrorProperty [webservices.@]
564 HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf,
565 ULONG size )
567 struct error *error = (struct error *)handle;
569 TRACE( "%p %u %p %u\n", handle, id, buf, size );
570 return get_error_prop( error, id, buf, size );
573 /**************************************************************************
574 * WsGetErrorString [webservices.@]
576 HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str )
578 FIXME( "%p %u %p: stub\n", handle, index, str );
579 return E_NOTIMPL;
582 /**************************************************************************
583 * WsGetHeapProperty [webservices.@]
585 HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
586 ULONG size, WS_ERROR *error )
588 struct heap *heap = (struct heap *)handle;
590 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
591 if (error) FIXME( "ignoring error parameter\n" );
593 return get_heap_prop( heap, id, buf, size );
596 /**************************************************************************
597 * WsGetReaderNode [webservices.@]
599 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
600 WS_ERROR *error )
602 struct reader *reader = (struct reader *)handle;
604 TRACE( "%p %p %p\n", handle, node, error );
605 if (error) FIXME( "ignoring error parameter\n" );
607 if (!reader || !node) return E_INVALIDARG;
609 *node = &reader->current->hdr.node;
610 return S_OK;
613 /**************************************************************************
614 * WsGetReaderProperty [webservices.@]
616 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
617 void *buf, ULONG size, WS_ERROR *error )
619 struct reader *reader = (struct reader *)handle;
621 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
622 if (error) FIXME( "ignoring error parameter\n" );
624 if (!reader->input_type) return WS_E_INVALID_OPERATION;
626 if (id == WS_XML_READER_PROPERTY_CHARSET)
628 WS_CHARSET charset;
629 HRESULT hr;
631 if ((hr = get_reader_prop( reader, id, &charset, size )) != S_OK) return hr;
632 if (!charset) return WS_E_INVALID_FORMAT;
633 *(WS_CHARSET *)buf = charset;
634 return S_OK;
636 return get_reader_prop( reader, id, buf, size );
639 /**************************************************************************
640 * WsGetXmlAttribute [webservices.@]
642 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
643 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
645 FIXME( "%p %p %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
646 return E_NOTIMPL;
649 WS_XML_STRING *alloc_xml_string( const char *data, ULONG len )
651 WS_XML_STRING *ret;
653 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
654 ret->length = len;
655 ret->bytes = (BYTE *)(ret + 1);
656 ret->dictionary = NULL;
657 ret->id = 0;
658 if (data) memcpy( ret->bytes, data, len );
659 return ret;
662 static WS_XML_UTF8_TEXT *alloc_utf8_text( const char *data, ULONG len )
664 WS_XML_UTF8_TEXT *ret;
666 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
667 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
668 ret->value.length = len;
669 ret->value.bytes = (BYTE *)(ret + 1);
670 ret->value.dictionary = NULL;
671 ret->value.id = 0;
672 if (data) memcpy( ret->value.bytes, data, len );
673 return ret;
676 static inline BOOL read_end_of_data( struct reader *reader )
678 return reader->read_pos >= reader->read_size;
681 static inline const char *read_current_ptr( struct reader *reader )
683 return &reader->read_bufptr[reader->read_pos];
686 /* UTF-8 support based on libs/wine/utf8.c */
688 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
689 static const char utf8_length[128] =
691 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
692 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
693 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
694 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
695 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
696 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
697 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
698 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
701 /* first byte mask depending on UTF-8 sequence length */
702 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
704 /* minimum Unicode value depending on UTF-8 sequence length */
705 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
707 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
709 unsigned int len, res;
710 unsigned char ch = reader->read_bufptr[reader->read_pos];
711 const char *end;
713 if (reader->read_pos >= reader->read_size) return 0;
715 if (ch < 0x80)
717 *skip = 1;
718 return ch;
720 len = utf8_length[ch - 0x80];
721 if (reader->read_pos + len >= reader->read_size) return 0;
722 end = reader->read_bufptr + reader->read_pos + len;
723 res = ch & utf8_mask[len];
725 switch (len)
727 case 3:
728 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
729 res = (res << 6) | ch;
730 case 2:
731 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
732 res = (res << 6) | ch;
733 case 1:
734 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
735 res = (res << 6) | ch;
736 if (res < utf8_minval[len]) break;
737 *skip = len + 1;
738 return res;
741 return 0;
744 static inline void read_skip( struct reader *reader, unsigned int count )
746 while (reader->read_pos < reader->read_size && count)
748 reader->read_pos++;
749 count--;
753 static inline BOOL read_isnamechar( unsigned int ch )
755 /* FIXME: incomplete */
756 return (ch >= 'A' && ch <= 'Z') ||
757 (ch >= 'a' && ch <= 'z') ||
758 (ch >= '0' && ch <= '9') ||
759 ch == '_' || ch == '-' || ch == '.' || ch == ':';
762 static inline BOOL read_isspace( unsigned int ch )
764 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
767 static inline void read_skip_whitespace( struct reader *reader )
769 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
770 reader->read_pos++;
773 static inline int read_cmp( struct reader *reader, const char *str, int len )
775 const char *ptr = read_current_ptr( reader );
777 if (len < 0) len = strlen( str );
778 if (reader->read_pos + len > reader->read_size) return -1;
779 while (len--)
781 if (*str != *ptr) return *ptr - *str;
782 str++; ptr++;
784 return 0;
787 static HRESULT read_xmldecl( struct reader *reader )
789 if (!reader->read_size) return WS_E_INVALID_FORMAT;
791 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
793 reader->state = READER_STATE_BOF;
794 return S_OK;
796 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
797 read_skip( reader, 6 );
799 /* FIXME: parse attributes */
800 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
801 reader->read_pos++;
803 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
804 read_skip( reader, 2 );
806 reader->state = READER_STATE_BOF;
807 return S_OK;
810 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
812 if (elem->attributeCount)
814 WS_XML_ATTRIBUTE **tmp;
815 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
816 return E_OUTOFMEMORY;
817 elem->attributes = tmp;
819 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
820 elem->attributes[elem->attributeCount++] = attr;
821 return S_OK;
824 static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
826 WS_XML_ATTRIBUTE *attr;
827 WS_XML_UTF8_TEXT *text;
828 unsigned int len = 0, ch, skip, quote;
829 const char *start;
830 HRESULT hr = WS_E_INVALID_FORMAT;
832 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
834 start = read_current_ptr( reader );
835 for (;;)
837 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
838 if (!read_isnamechar( ch )) break;
839 read_skip( reader, skip );
840 len += skip;
842 if (!len) goto error;
844 hr = E_OUTOFMEMORY;
845 if (!(attr->localName = alloc_xml_string( start, len ))) goto error;
846 if (!(attr->prefix = alloc_xml_string( NULL, 0 ))) goto error;
847 attr->prefix->bytes = NULL;
848 if (!(attr->ns = alloc_xml_string( NULL, 0 ))) goto error;
849 attr->ns->bytes = NULL;
851 hr = WS_E_INVALID_FORMAT;
852 read_skip_whitespace( reader );
853 if (read_cmp( reader, "=", 1 )) goto error;
854 read_skip( reader, 1 );
856 read_skip_whitespace( reader );
857 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) goto error;
858 quote = read_utf8_char( reader, &skip );
859 read_skip( reader, 1 );
861 len = 0;
862 start = read_current_ptr( reader );
863 for (;;)
865 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
866 if (ch == quote) break;
867 read_skip( reader, skip );
868 len += skip;
870 read_skip( reader, 1 );
872 if (!(text = alloc_utf8_text( start, len )))
874 free_attribute( attr );
875 return E_OUTOFMEMORY;
877 attr->value = (WS_XML_TEXT *)text;
878 attr->singleQuote = (quote == '\'');
880 *ret = attr;
881 return S_OK;
883 error:
884 free_attribute( attr );
885 return hr;
888 static HRESULT read_element( struct reader *reader )
890 unsigned int len = 0, ch, skip;
891 const char *start;
892 struct node *node;
893 WS_XML_ELEMENT_NODE *elem;
894 WS_XML_ATTRIBUTE *attr;
895 HRESULT hr = WS_E_INVALID_FORMAT;
897 if (read_end_of_data( reader ))
899 struct list *eof = list_tail( &reader->root->children );
900 reader->current = LIST_ENTRY( eof, struct node, entry );
901 reader->state = READER_STATE_EOF;
902 return S_OK;
905 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
906 elem = (WS_XML_ELEMENT_NODE *)node;
908 if (read_cmp( reader, "<", 1 )) goto error;
909 read_skip( reader, 1 );
911 start = read_current_ptr( reader );
912 for (;;)
914 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
915 if (!read_isnamechar( ch )) break;
916 read_skip( reader, skip );
917 len += skip;
919 if (!len) goto error;
921 hr = E_OUTOFMEMORY;
922 if (!(elem->localName = alloc_xml_string( start, len ))) goto error;
923 if (!(elem->prefix = alloc_xml_string( NULL, 0 ))) goto error;
924 elem->prefix->bytes = NULL;
925 if (!(elem->ns = alloc_xml_string( NULL, 0 ))) goto error;
927 for (;;)
929 read_skip_whitespace( reader );
930 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
931 if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
932 if ((hr = append_attribute( elem, attr )) != S_OK)
934 free_attribute( attr );
935 goto error;
939 read_skip_whitespace( reader );
940 if (read_cmp( reader, ">", 1 ) && read_cmp( reader, "/>", 2 ))
942 hr = WS_E_INVALID_FORMAT;
943 goto error;
946 read_insert_node( reader, reader->current, node );
947 if (!read_cmp( reader, "/>", 2 ))
949 read_skip( reader, 2 );
950 reader->current = reader->current->parent;
951 reader->state = READER_STATE_STARTENDELEMENT;
953 else
955 read_skip( reader, 1 );
956 reader->state = READER_STATE_STARTELEMENT;
958 return S_OK;
960 error:
961 free_node( node );
962 return hr;
965 static HRESULT read_text( struct reader *reader )
967 unsigned int len = 0, ch, skip;
968 const char *start;
969 struct node *node;
970 WS_XML_TEXT_NODE *text;
971 WS_XML_UTF8_TEXT *utf8;
973 start = read_current_ptr( reader );
974 for (;;)
976 if (read_end_of_data( reader )) break;
977 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
978 if (ch == '<') break;
979 read_skip( reader, skip );
980 len += skip;
983 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
984 text = (WS_XML_TEXT_NODE *)node;
985 if (!(utf8 = alloc_utf8_text( start, len )))
987 heap_free( node );
988 return E_OUTOFMEMORY;
990 text->text = (WS_XML_TEXT *)utf8;
992 read_insert_node( reader, reader->current, node );
993 reader->state = READER_STATE_TEXT;
994 return S_OK;
997 static HRESULT read_startelement( struct reader *reader )
999 if (!read_cmp( reader, "<", 1 )) return read_element( reader );
1000 return read_text( reader );
1003 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
1005 HRESULT hr;
1007 switch (reader->state)
1009 case READER_STATE_INITIAL:
1010 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
1011 break;
1013 case READER_STATE_STARTELEMENT:
1014 if (found) *found = TRUE;
1015 return S_OK;
1017 default:
1018 break;
1021 read_skip_whitespace( reader );
1022 if ((hr = read_element( reader )) == S_OK && found)
1024 if (reader->state == READER_STATE_STARTELEMENT)
1025 *found = TRUE;
1026 else
1027 *found = FALSE;
1030 return hr;
1033 static BOOL cmp_localname( const char *name1, ULONG len1, const char *name2, ULONG len2 )
1035 ULONG i;
1036 if (len1 != len2) return FALSE;
1037 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return FALSE; }
1038 return TRUE;
1041 static struct node *find_parent_element( struct node *node, const char *localname, ULONG len )
1043 struct node *parent;
1044 WS_XML_STRING *name;
1046 for (parent = node; parent; parent = parent->parent)
1048 if (parent->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT) continue;
1049 name = ((WS_XML_ELEMENT_NODE *)parent)->localName;
1050 if (!cmp_localname( (const char *)name->bytes, name->length, localname, len )) continue;
1051 return parent;
1053 return NULL;
1056 static HRESULT read_endelement( struct reader *reader )
1058 struct node *node, *parent;
1059 unsigned int len = 0, ch, skip;
1060 const char *start;
1062 switch (reader->state)
1064 case READER_STATE_TEXT:
1065 case READER_STATE_STARTELEMENT:
1066 case READER_STATE_STARTENDELEMENT:
1067 break;
1068 default:
1069 return WS_E_INVALID_FORMAT;
1072 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
1073 read_skip( reader, 2 );
1075 start = read_current_ptr( reader );
1076 for (;;)
1078 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1079 if (ch == '>')
1081 read_skip( reader, 1 );
1082 break;
1084 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
1085 read_skip( reader, skip );
1086 len += skip;
1088 if (!(parent = find_parent_element( reader->current, start, len )))
1089 return WS_E_INVALID_FORMAT;
1091 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1092 read_insert_node( reader, parent, node );
1093 reader->state = READER_STATE_ENDELEMENT;
1094 return S_OK;
1097 static HRESULT read_comment( struct reader *reader )
1099 unsigned int len = 0, ch, skip;
1100 const char *start;
1101 struct node *node;
1102 WS_XML_COMMENT_NODE *comment;
1104 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
1105 read_skip( reader, 4 );
1107 start = read_current_ptr( reader );
1108 for (;;)
1110 if (!read_cmp( reader, "-->", 3 ))
1112 read_skip( reader, 3 );
1113 break;
1115 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1116 read_skip( reader, skip );
1117 len += skip;
1120 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
1121 comment = (WS_XML_COMMENT_NODE *)node;
1122 if (!(comment->value.bytes = heap_alloc( len )))
1124 heap_free( node );
1125 return E_OUTOFMEMORY;
1127 memcpy( comment->value.bytes, start, len );
1128 comment->value.length = len;
1130 read_insert_node( reader, reader->current, node );
1131 reader->state = READER_STATE_COMMENT;
1132 return S_OK;
1135 static HRESULT read_node( struct reader *reader )
1137 HRESULT hr;
1139 for (;;)
1141 if (read_end_of_data( reader ))
1143 struct list *eof = list_tail( &reader->root->children );
1144 reader->current = LIST_ENTRY( eof, struct node, entry );
1145 reader->state = READER_STATE_EOF;
1146 return S_OK;
1148 if (!read_cmp( reader, "<?", 2 ))
1150 hr = read_xmldecl( reader );
1151 if (FAILED( hr )) return hr;
1153 else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
1154 else if (!read_cmp( reader, "<!", 2 )) return read_comment( reader );
1155 else if (!read_cmp( reader, "<", 1 )) return read_startelement( reader );
1156 else return read_text( reader );
1160 /**************************************************************************
1161 * WsReadEndElement [webservices.@]
1163 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
1165 struct reader *reader = (struct reader *)handle;
1167 TRACE( "%p %p\n", handle, error );
1168 if (error) FIXME( "ignoring error parameter\n" );
1170 if (!reader) return E_INVALIDARG;
1171 return read_endelement( reader );
1174 /**************************************************************************
1175 * WsReadNode [webservices.@]
1177 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
1179 struct reader *reader = (struct reader *)handle;
1181 TRACE( "%p %p\n", handle, error );
1182 if (error) FIXME( "ignoring error parameter\n" );
1184 if (!reader) return E_INVALIDARG;
1185 return read_node( reader );
1188 /**************************************************************************
1189 * WsReadStartElement [webservices.@]
1191 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
1193 struct reader *reader = (struct reader *)handle;
1195 TRACE( "%p %p\n", handle, error );
1196 if (error) FIXME( "ignoring error parameter\n" );
1198 if (!reader) return E_INVALIDARG;
1199 return read_startelement( reader );
1202 /**************************************************************************
1203 * WsReadToStartElement [webservices.@]
1205 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
1206 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
1208 struct reader *reader = (struct reader *)handle;
1210 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
1211 if (error) FIXME( "ignoring error parameter\n" );
1213 if (!reader) return E_INVALIDARG;
1214 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
1216 return read_to_startelement( reader, found );
1219 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
1221 struct list *ptr;
1222 BOOL success = FALSE;
1223 HRESULT hr = S_OK;
1225 if (!read_end_of_data( reader ))
1227 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
1228 if (hr != S_OK) return hr;
1230 switch (move)
1232 case WS_MOVE_TO_FIRST_NODE:
1233 if ((ptr = list_head( &reader->current->parent->children )))
1235 reader->current = LIST_ENTRY( ptr, struct node, entry );
1236 success = TRUE;
1238 break;
1240 case WS_MOVE_TO_NEXT_NODE:
1241 if ((ptr = list_next( &reader->current->parent->children, &reader->current->entry )))
1243 reader->current = LIST_ENTRY( ptr, struct node, entry );
1244 success = TRUE;
1246 break;
1248 case WS_MOVE_TO_PREVIOUS_NODE:
1249 if ((ptr = list_prev( &reader->current->parent->children, &reader->current->entry )))
1251 reader->current = LIST_ENTRY( ptr, struct node, entry );
1252 success = TRUE;
1254 break;
1256 case WS_MOVE_TO_CHILD_NODE:
1257 if ((ptr = list_head( &reader->current->children )))
1259 reader->current = LIST_ENTRY( ptr, struct node, entry );
1260 success = TRUE;
1262 break;
1264 case WS_MOVE_TO_BOF:
1265 reader->current = reader->root;
1266 success = TRUE;
1267 break;
1269 case WS_MOVE_TO_EOF:
1270 if ((ptr = list_tail( &reader->root->children )))
1272 reader->current = LIST_ENTRY( ptr, struct node, entry );
1273 success = TRUE;
1275 break;
1277 default:
1278 FIXME( "unhandled move %u\n", move );
1279 return E_NOTIMPL;
1282 if (found)
1284 *found = success;
1285 return S_OK;
1287 return success ? S_OK : WS_E_INVALID_FORMAT;
1290 /**************************************************************************
1291 * WsMoveReader [webservices.@]
1293 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
1295 struct reader *reader = (struct reader *)handle;
1297 TRACE( "%p %u %p %p\n", handle, move, found, error );
1298 if (error) FIXME( "ignoring error parameter\n" );
1300 if (!reader) return E_INVALIDARG;
1301 if (!reader->input_type) return WS_E_INVALID_OPERATION;
1303 return read_move_to( reader, move, found );
1306 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
1308 WCHAR *ret;
1310 switch (text->textType)
1312 case WS_XML_TEXT_TYPE_UTF8:
1314 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
1315 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
1316 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
1317 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
1318 ret[len] = 0;
1319 break;
1321 default:
1322 FIXME( "unhandled type %u\n", text->textType );
1323 return NULL;
1326 return ret;
1329 #define MAX_INT8 0x7f
1330 #define MIN_INT8 (-MAX_INT8 - 1)
1331 #define MAX_INT16 0x7fff
1332 #define MIN_INT16 (-MAX_INT16 - 1)
1333 #define MAX_INT32 0x7fffffff
1334 #define MIN_INT32 (-MAX_INT32 - 1)
1335 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1336 #define MIN_INT64 (-MAX_INT64 - 1)
1337 #define MAX_UINT8 0xff
1338 #define MAX_UINT16 0xffff
1339 #define MAX_UINT32 0xffffffff
1340 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1342 static HRESULT str_to_int64( const char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
1344 BOOL negative = FALSE;
1345 const char *ptr = str;
1347 *ret = 0;
1348 while (len && read_isspace( *ptr )) { ptr++; len--; }
1349 while (len && read_isspace( ptr[len - 1] )) { len--; }
1350 if (!len) return WS_E_INVALID_FORMAT;
1352 if (*ptr == '-')
1354 negative = TRUE;
1355 ptr++;
1356 len--;
1358 if (!len) return WS_E_INVALID_FORMAT;
1360 while (len--)
1362 int val;
1364 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1365 val = *ptr - '0';
1366 if (negative) val = -val;
1368 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
1369 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
1371 return WS_E_NUMERIC_OVERFLOW;
1373 *ret = *ret * 10 + val;
1374 ptr++;
1377 return S_OK;
1380 static HRESULT str_to_uint64( const char *str, ULONG len, UINT64 max, UINT64 *ret )
1382 const char *ptr = str;
1384 *ret = 0;
1385 while (len && read_isspace( *ptr )) { ptr++; len--; }
1386 while (len && read_isspace( ptr[len - 1] )) { len--; }
1387 if (!len) return WS_E_INVALID_FORMAT;
1389 while (len--)
1391 unsigned int val;
1393 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1394 val = *ptr - '0';
1396 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
1397 *ret = *ret * 10 + val;
1398 ptr++;
1401 return S_OK;
1404 /**************************************************************************
1405 * WsReadType [webservices.@]
1407 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
1408 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
1409 ULONG value_size, WS_ERROR *error )
1411 struct reader *reader = (struct reader *)handle;
1412 WS_XML_TEXT_NODE *text;
1414 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
1415 value_size, error );
1416 if (error) FIXME( "ignoring error parameter\n" );
1418 if (!reader || !value) return E_INVALIDARG;
1420 if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_TEXT)
1422 FIXME( "only text nodes are supported\n" );
1423 return E_NOTIMPL;
1425 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
1426 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
1428 FIXME( "text type %u not supported\n", text->text->textType );
1429 return E_NOTIMPL;
1432 switch (mapping)
1434 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1435 break;
1436 default:
1437 FIXME( "mapping %u not supported\n", mapping );
1438 return E_NOTIMPL;
1441 switch (type)
1443 case WS_BOOL_TYPE:
1445 WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
1446 ULONG len = utf8->value.length;
1447 BOOL *ret = value;
1449 if (value_size != sizeof(BOOL)) return E_INVALIDARG;
1451 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) *ret = TRUE;
1452 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) *ret = TRUE;
1453 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) *ret = FALSE;
1454 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) *ret = FALSE;
1455 else return WS_E_INVALID_FORMAT;
1456 break;
1458 case WS_INT8_TYPE:
1460 WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
1461 INT8 *ret = value;
1462 HRESULT hr;
1463 INT64 val;
1465 if (value_size != sizeof(INT8)) return E_INVALIDARG;
1466 hr = str_to_int64( (const char *)utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val );
1467 if (hr != S_OK) return hr;
1468 *ret = val;
1469 break;
1471 case WS_INT16_TYPE:
1473 WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
1474 INT16 *ret = value;
1475 HRESULT hr;
1476 INT64 val;
1478 if (value_size != sizeof(INT16)) return E_INVALIDARG;
1479 hr = str_to_int64( (const char *)utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val );
1480 if (hr != S_OK) return hr;
1481 *ret = val;
1482 break;
1484 case WS_INT32_TYPE:
1486 WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
1487 INT32 *ret = value;
1488 HRESULT hr;
1489 INT64 val;
1491 if (value_size != sizeof(INT32)) return E_INVALIDARG;
1492 hr = str_to_int64( (const char *)utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val );
1493 if (hr != S_OK) return hr;
1494 *ret = val;
1495 break;
1497 case WS_INT64_TYPE:
1499 WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
1500 INT64 val, *ret = value;
1501 HRESULT hr;
1503 if (value_size != sizeof(INT64)) return E_INVALIDARG;
1504 hr = str_to_int64( (const char *)utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val );
1505 if (hr != S_OK) return hr;
1506 *ret = val;
1507 break;
1509 case WS_UINT8_TYPE:
1511 WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
1512 UINT8 *ret = value;
1513 HRESULT hr;
1514 UINT64 val;
1516 if (value_size != sizeof(UINT8)) return E_INVALIDARG;
1517 hr = str_to_uint64( (const char *)utf8->value.bytes, utf8->value.length, MAX_UINT8, &val );
1518 if (hr != S_OK) return hr;
1519 *ret = val;
1520 break;
1522 case WS_UINT16_TYPE:
1524 WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
1525 UINT16 *ret = value;
1526 HRESULT hr;
1527 UINT64 val;
1529 if (value_size != sizeof(UINT16)) return E_INVALIDARG;
1530 hr = str_to_uint64( (const char *)utf8->value.bytes, utf8->value.length, MAX_UINT16, &val );
1531 if (hr != S_OK) return hr;
1532 *ret = val;
1533 break;
1535 case WS_UINT32_TYPE:
1537 WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
1538 UINT32 *ret = value;
1539 HRESULT hr;
1540 UINT64 val;
1542 if (value_size != sizeof(UINT32)) return E_INVALIDARG;
1543 hr = str_to_uint64( (const char *)utf8->value.bytes, utf8->value.length, MAX_UINT32, &val );
1544 if (hr != S_OK) return hr;
1545 *ret = val;
1546 break;
1548 case WS_UINT64_TYPE:
1550 WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
1551 UINT64 val, *ret = value;
1552 HRESULT hr;
1554 if (value_size != sizeof(UINT64)) return E_INVALIDARG;
1555 hr = str_to_uint64( (const char *)utf8->value.bytes, utf8->value.length, MAX_UINT64, &val );
1556 if (hr != S_OK) return hr;
1557 *ret = val;
1558 break;
1560 case WS_WSZ_TYPE:
1562 WCHAR *str, **ret = value;
1564 if (value_size != sizeof(WCHAR *)) return E_INVALIDARG;
1565 if (!(str = xmltext_to_widechar( heap, text->text ))) return E_OUTOFMEMORY;
1566 *ret = str;
1567 break;
1569 default:
1570 FIXME( "type %u not supported\n", type );
1571 return E_NOTIMPL;
1574 return S_OK;
1577 /**************************************************************************
1578 * WsSetErrorProperty [webservices.@]
1580 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
1581 ULONG size )
1583 struct error *error = (struct error *)handle;
1585 TRACE( "%p %u %p %u\n", handle, id, value, size );
1587 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
1588 return set_error_prop( error, id, value, size );
1591 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
1593 static const char bom[] = {0xef,0xbb,0xbf};
1594 const unsigned char *p = data;
1596 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
1597 (size > 2 && !(*offset = 0));
1600 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
1602 static const char bom[] = {0xff,0xfe};
1603 const unsigned char *p = data;
1605 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
1606 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
1609 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
1611 WS_CHARSET ret = 0;
1613 /* FIXME: parse xml declaration */
1615 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
1616 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
1617 else
1619 FIXME( "charset not recognized\n" );
1620 return 0;
1623 TRACE( "detected charset %u\n", ret );
1624 return ret;
1627 static void set_input_buffer( struct reader *reader, const char *data, ULONG size )
1629 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
1630 reader->input_data = data;
1631 reader->input_size = size;
1633 reader->read_size = reader->input_size;
1634 reader->read_pos = 0;
1635 reader->read_bufptr = reader->input_data;
1638 /**************************************************************************
1639 * WsSetInput [webservices.@]
1641 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
1642 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
1643 ULONG count, WS_ERROR *error )
1645 struct reader *reader = (struct reader *)handle;
1646 struct node *node;
1647 HRESULT hr;
1648 ULONG i, offset = 0;
1650 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
1651 if (error) FIXME( "ignoring error parameter\n" );
1653 if (!reader) return E_INVALIDARG;
1655 for (i = 0; i < count; i++)
1657 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
1658 if (hr != S_OK) return hr;
1661 if ((hr = read_init_state( reader )) != S_OK) return hr;
1663 switch (encoding->encodingType)
1665 case WS_XML_READER_ENCODING_TYPE_TEXT:
1667 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
1668 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
1669 WS_CHARSET charset = text->charSet;
1671 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
1673 FIXME( "charset detection on input type %u not supported\n", input->inputType );
1674 return E_NOTIMPL;
1677 if (charset == WS_CHARSET_AUTO)
1678 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
1680 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
1681 if (hr != S_OK) return hr;
1682 break;
1684 default:
1685 FIXME( "encoding type %u not supported\n", encoding->encodingType );
1686 return E_NOTIMPL;
1688 switch (input->inputType)
1690 case WS_XML_READER_INPUT_TYPE_BUFFER:
1692 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
1693 set_input_buffer( reader, (const char *)buf->encodedData + offset, buf->encodedDataSize - offset );
1694 break;
1696 default:
1697 FIXME( "input type %u not supported\n", input->inputType );
1698 return E_NOTIMPL;
1701 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
1702 read_insert_bof( reader, node );
1703 return S_OK;
1706 /**************************************************************************
1707 * WsSetInputToBuffer [webservices.@]
1709 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
1710 const WS_XML_READER_PROPERTY *properties, ULONG count,
1711 WS_ERROR *error )
1713 struct reader *reader = (struct reader *)handle;
1714 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
1715 WS_CHARSET charset;
1716 struct node *node;
1717 HRESULT hr;
1718 ULONG i, offset = 0;
1720 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
1721 if (error) FIXME( "ignoring error parameter\n" );
1723 if (!reader || !xmlbuf) return E_INVALIDARG;
1725 for (i = 0; i < count; i++)
1727 hr = set_reader_prop( reader, properties[i].id, properties[i].value, properties[i].valueSize );
1728 if (hr != S_OK) return hr;
1731 if ((hr = read_init_state( reader )) != S_OK) return hr;
1733 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
1734 hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
1735 if (hr != S_OK) return hr;
1737 set_input_buffer( reader, (const char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
1738 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
1739 read_insert_bof( reader, node );
1740 return S_OK;
1743 /**************************************************************************
1744 * WsXmlStringEquals [webservices.@]
1746 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
1748 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
1749 if (error) FIXME( "ignoring error parameter\n" );
1751 if (!str1 || !str2) return E_INVALIDARG;
1753 if (str1->length != str2->length) return S_FALSE;
1754 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
1755 return S_FALSE;