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
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 static const char *debugstr_xmlstr( const WS_XML_STRING
*str
)
34 if (!str
) return "(null)";
35 return debugstr_an( (const char *)str
->bytes
, str
->length
);
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 */
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]);
60 ULONG i
, size
= sizeof(*ret
) + count
* sizeof(WS_ERROR_PROPERTY
);
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
;
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
)
82 memcpy( error
->prop
[id
].value
, value
, size
);
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
)
91 memcpy( buf
, error
->prop
[id
].value
, error
->prop
[id
].valueSize
);
95 /**************************************************************************
96 * WsCreateError [webservices.@]
98 HRESULT WINAPI
WsCreateError( const WS_ERROR_PROPERTY
*properties
, ULONG count
, WS_ERROR
**handle
)
101 LANGID langid
= GetUserDefaultUILanguage();
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
)
118 hr
= set_error_prop( error
, properties
[i
].id
, properties
[i
].value
, properties
[i
].valueSize
);
126 *handle
= (WS_ERROR
*)error
;
130 /**************************************************************************
131 * WsFreeError [webservices.@]
133 void WINAPI
WsFreeError( WS_ERROR
*handle
)
135 struct error
*error
= (struct error
*)handle
;
137 TRACE( "%p\n", handle
);
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 */
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_free( WS_HEAP
*handle
, void *ptr
)
169 struct heap
*heap
= (struct heap
*)handle
;
170 HeapFree( heap
->handle
, 0, ptr
);
173 /**************************************************************************
174 * WsAlloc [webservices.@]
176 HRESULT WINAPI
WsAlloc( WS_HEAP
*handle
, SIZE_T size
, void **ptr
, WS_ERROR
*error
)
180 TRACE( "%p %u %p %p\n", handle
, (ULONG
)size
, ptr
, error
);
181 if (error
) FIXME( "ignoring error parameter\n" );
183 if (!handle
|| !ptr
) return E_INVALIDARG
;
185 if (!(mem
= ws_alloc( handle
, size
))) return E_OUTOFMEMORY
;
190 static struct heap
*alloc_heap(void)
192 static const ULONG count
= sizeof(heap_props
)/sizeof(heap_props
[0]);
194 ULONG i
, size
= sizeof(*ret
) + count
* sizeof(WS_HEAP_PROPERTY
);
197 for (i
= 0; i
< count
; i
++) size
+= heap_props
[i
].size
;
198 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
200 ptr
= (char *)&ret
->prop
[count
];
201 for (i
= 0; i
< count
; i
++)
203 ret
->prop
[i
].value
= ptr
;
204 ret
->prop
[i
].valueSize
= heap_props
[i
].size
;
205 ptr
+= ret
->prop
[i
].valueSize
;
207 ret
->prop_count
= count
;
211 static HRESULT
set_heap_prop( struct heap
*heap
, WS_HEAP_PROPERTY_ID id
, const void *value
, ULONG size
)
213 if (id
>= heap
->prop_count
|| size
!= heap_props
[id
].size
|| heap_props
[id
].readonly
)
216 memcpy( heap
->prop
[id
].value
, value
, size
);
220 static HRESULT
get_heap_prop( struct heap
*heap
, WS_HEAP_PROPERTY_ID id
, void *buf
, ULONG size
)
222 if (id
>= heap
->prop_count
|| size
!= heap_props
[id
].size
)
225 memcpy( buf
, heap
->prop
[id
].value
, heap
->prop
[id
].valueSize
);
229 /**************************************************************************
230 * WsCreateHeap [webservices.@]
232 HRESULT WINAPI
WsCreateHeap( SIZE_T max_size
, SIZE_T trim_size
, const WS_HEAP_PROPERTY
*properties
,
233 ULONG count
, WS_HEAP
**handle
, WS_ERROR
*error
)
237 TRACE( "%u %u %p %u %p %p\n", (ULONG
)max_size
, (ULONG
)trim_size
, properties
, count
, handle
, error
);
238 if (error
) FIXME( "ignoring error parameter\n" );
240 if (!handle
|| count
) return E_INVALIDARG
;
241 if (!(heap
= alloc_heap())) return E_OUTOFMEMORY
;
243 set_heap_prop( heap
, WS_HEAP_PROPERTY_MAX_SIZE
, &max_size
, sizeof(max_size
) );
244 set_heap_prop( heap
, WS_HEAP_PROPERTY_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
246 if (!(heap
->handle
= HeapCreate( 0, 0, max_size
)))
249 return E_OUTOFMEMORY
;
252 *handle
= (WS_HEAP
*)heap
;
256 /**************************************************************************
257 * WsFreeHeap [webservices.@]
259 void WINAPI
WsFreeHeap( WS_HEAP
*handle
)
261 struct heap
*heap
= (struct heap
*)handle
;
263 TRACE( "%p\n", handle
);
266 HeapDestroy( heap
->handle
);
272 WS_XML_ELEMENT_NODE hdr
;
275 struct list children
;
278 static struct node
*alloc_node( WS_XML_NODE_TYPE type
)
282 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
283 ret
->hdr
.node
.nodeType
= type
;
284 list_init( &ret
->entry
);
285 list_init( &ret
->children
);
289 static void free_attribute( WS_XML_ATTRIBUTE
*attr
)
292 heap_free( attr
->prefix
);
293 heap_free( attr
->localName
);
294 heap_free( attr
->ns
);
295 heap_free( attr
->value
);
299 static void free_node( struct node
*node
)
302 switch (node
->hdr
.node
.nodeType
)
304 case WS_XML_NODE_TYPE_ELEMENT
:
306 WS_XML_ELEMENT_NODE
*elem
= (WS_XML_ELEMENT_NODE
*)node
;
309 for (i
= 0; i
< elem
->attributeCount
; i
++) free_attribute( elem
->attributes
[i
] );
310 heap_free( elem
->attributes
);
311 heap_free( elem
->prefix
);
312 heap_free( elem
->localName
);
313 heap_free( elem
->ns
);
316 case WS_XML_NODE_TYPE_TEXT
:
318 WS_XML_TEXT_NODE
*text
= (WS_XML_TEXT_NODE
*)node
;
319 heap_free( text
->text
);
322 case WS_XML_NODE_TYPE_COMMENT
:
324 WS_XML_COMMENT_NODE
*comment
= (WS_XML_COMMENT_NODE
*)node
;
325 heap_free( comment
->value
.bytes
);
327 case WS_XML_NODE_TYPE_END_ELEMENT
:
328 case WS_XML_NODE_TYPE_EOF
:
329 case WS_XML_NODE_TYPE_BOF
:
333 ERR( "unhandled type %u\n", node
->hdr
.node
.nodeType
);
339 static void destroy_nodes( struct node
*node
)
344 while ((ptr
= list_head( &node
->children
)))
346 struct node
*child
= LIST_ENTRY( ptr
, struct node
, entry
);
347 list_remove( &child
->entry
);
348 destroy_nodes( child
);
360 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
361 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
362 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
363 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
364 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
365 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
366 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
367 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
368 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
369 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
370 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
371 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
372 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
373 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
374 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
379 READER_STATE_INITIAL
,
381 READER_STATE_STARTELEMENT
,
382 READER_STATE_STARTENDELEMENT
,
384 READER_STATE_ENDELEMENT
,
385 READER_STATE_COMMENT
,
393 const char *read_bufptr
;
394 enum reader_state state
;
396 struct node
*current
;
397 WS_XML_READER_INPUT_TYPE input_type
;
398 const char *input_data
;
401 WS_XML_READER_PROPERTY prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
404 static struct reader
*alloc_reader(void)
406 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
408 ULONG i
, size
= sizeof(*ret
) + count
* sizeof(WS_XML_READER_PROPERTY
);
411 for (i
= 0; i
< count
; i
++) size
+= reader_props
[i
].size
;
412 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
414 ptr
= (char *)&ret
->prop
[count
];
415 for (i
= 0; i
< count
; i
++)
417 ret
->prop
[i
].value
= ptr
;
418 ret
->prop
[i
].valueSize
= reader_props
[i
].size
;
419 ptr
+= ret
->prop
[i
].valueSize
;
421 ret
->prop_count
= count
;
425 static HRESULT
set_reader_prop( struct reader
*reader
, WS_XML_READER_PROPERTY_ID id
, const void *value
, ULONG size
)
427 if (id
>= reader
->prop_count
|| size
!= reader_props
[id
].size
|| reader_props
[id
].readonly
)
430 memcpy( reader
->prop
[id
].value
, value
, size
);
434 static HRESULT
get_reader_prop( struct reader
*reader
, WS_XML_READER_PROPERTY_ID id
, void *buf
, ULONG size
)
436 if (id
>= reader
->prop_count
|| size
!= reader_props
[id
].size
)
439 memcpy( buf
, reader
->prop
[id
].value
, reader
->prop
[id
].valueSize
);
443 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
445 if (!reader
->root
) reader
->root
= eof
;
448 eof
->parent
= reader
->root
;
449 list_add_tail( &reader
->root
->children
, &eof
->entry
);
451 reader
->current
= eof
;
454 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
456 reader
->root
->parent
= bof
;
457 list_add_tail( &bof
->children
, &reader
->root
->entry
);
458 reader
->current
= reader
->root
= bof
;
461 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
463 node
->parent
= parent
;
464 if (node
->parent
== reader
->root
)
466 struct list
*eof
= list_tail( &reader
->root
->children
);
467 list_add_before( eof
, &node
->entry
);
469 else list_add_tail( &parent
->children
, &node
->entry
);
470 reader
->current
= node
;
473 static HRESULT
read_init_state( struct reader
*reader
)
477 destroy_nodes( reader
->root
);
479 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
480 read_insert_eof( reader
, node
);
481 reader
->state
= READER_STATE_INITIAL
;
485 /**************************************************************************
486 * WsCreateReader [webservices.@]
488 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
489 WS_XML_READER
**handle
, WS_ERROR
*error
)
491 struct reader
*reader
;
492 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
493 WS_CHARSET charset
= WS_CHARSET_UTF8
;
494 BOOL read_decl
= TRUE
;
497 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
498 if (error
) FIXME( "ignoring error parameter\n" );
500 if (!handle
) return E_INVALIDARG
;
501 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
503 set_reader_prop( reader
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
504 set_reader_prop( reader
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
505 set_reader_prop( reader
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
506 set_reader_prop( reader
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
507 set_reader_prop( reader
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
509 for (i
= 0; i
< count
; i
++)
511 hr
= set_reader_prop( reader
, properties
[i
].id
, properties
[i
].value
, properties
[i
].valueSize
);
519 if ((hr
= read_init_state( reader
)) != S_OK
)
525 *handle
= (WS_XML_READER
*)reader
;
529 /**************************************************************************
530 * WsFreeReader [webservices.@]
532 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
534 struct reader
*reader
= (struct reader
*)handle
;
536 TRACE( "%p\n", handle
);
539 destroy_nodes( reader
->root
);
543 /**************************************************************************
544 * WsFillReader [webservices.@]
546 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
549 struct reader
*reader
= (struct reader
*)handle
;
551 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
552 if (error
) FIXME( "ignoring error parameter\n" );
554 if (!reader
) return E_INVALIDARG
;
556 /* FIXME: add support for stream input */
557 reader
->read_size
= min( min_size
, reader
->input_size
);
558 reader
->read_pos
= 0;
563 /**************************************************************************
564 * WsGetErrorProperty [webservices.@]
566 HRESULT WINAPI
WsGetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, void *buf
,
569 struct error
*error
= (struct error
*)handle
;
571 TRACE( "%p %u %p %u\n", handle
, id
, buf
, size
);
572 return get_error_prop( error
, id
, buf
, size
);
575 /**************************************************************************
576 * WsGetErrorString [webservices.@]
578 HRESULT WINAPI
WsGetErrorString( WS_ERROR
*handle
, ULONG index
, WS_STRING
*str
)
580 FIXME( "%p %u %p: stub\n", handle
, index
, str
);
584 /**************************************************************************
585 * WsGetHeapProperty [webservices.@]
587 HRESULT WINAPI
WsGetHeapProperty( WS_HEAP
*handle
, WS_HEAP_PROPERTY_ID id
, void *buf
,
588 ULONG size
, WS_ERROR
*error
)
590 struct heap
*heap
= (struct heap
*)handle
;
592 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
593 if (error
) FIXME( "ignoring error parameter\n" );
595 return get_heap_prop( heap
, id
, buf
, size
);
598 /**************************************************************************
599 * WsGetReaderNode [webservices.@]
601 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
604 struct reader
*reader
= (struct reader
*)handle
;
606 TRACE( "%p %p %p\n", handle
, node
, error
);
607 if (error
) FIXME( "ignoring error parameter\n" );
609 if (!reader
|| !node
) return E_INVALIDARG
;
611 *node
= &reader
->current
->hdr
.node
;
615 /**************************************************************************
616 * WsGetReaderProperty [webservices.@]
618 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
619 void *buf
, ULONG size
, WS_ERROR
*error
)
621 struct reader
*reader
= (struct reader
*)handle
;
623 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
624 if (error
) FIXME( "ignoring error parameter\n" );
626 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
628 if (id
== WS_XML_READER_PROPERTY_CHARSET
)
633 if ((hr
= get_reader_prop( reader
, id
, &charset
, size
)) != S_OK
) return hr
;
634 if (!charset
) return WS_E_INVALID_FORMAT
;
635 *(WS_CHARSET
*)buf
= charset
;
638 return get_reader_prop( reader
, id
, buf
, size
);
641 /**************************************************************************
642 * WsGetXmlAttribute [webservices.@]
644 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
645 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
647 FIXME( "%p %p %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
651 static WS_XML_STRING
*alloc_xml_string( const char *data
, ULONG len
)
655 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
657 ret
->bytes
= (BYTE
*)(ret
+ 1);
658 ret
->dictionary
= NULL
;
660 if (data
) memcpy( ret
->bytes
, data
, len
);
664 static WS_XML_UTF8_TEXT
*alloc_utf8_text( const char *data
, ULONG len
)
666 WS_XML_UTF8_TEXT
*ret
;
668 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
669 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
670 ret
->value
.length
= len
;
671 ret
->value
.bytes
= (BYTE
*)(ret
+ 1);
672 ret
->value
.dictionary
= NULL
;
674 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
678 static inline BOOL
read_end_of_data( struct reader
*reader
)
680 return reader
->read_pos
>= reader
->read_size
;
683 static inline const char *read_current_ptr( struct reader
*reader
)
685 return &reader
->read_bufptr
[reader
->read_pos
];
688 /* UTF-8 support based on libs/wine/utf8.c */
690 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
691 static const char utf8_length
[128] =
693 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
694 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
695 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
696 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
697 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
698 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
699 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
700 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
703 /* first byte mask depending on UTF-8 sequence length */
704 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
706 /* minimum Unicode value depending on UTF-8 sequence length */
707 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
709 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
711 unsigned int len
, res
;
712 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
715 if (reader
->read_pos
>= reader
->read_size
) return 0;
722 len
= utf8_length
[ch
- 0x80];
723 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
724 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
;
725 res
= ch
& utf8_mask
[len
];
730 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
731 res
= (res
<< 6) | ch
;
733 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
734 res
= (res
<< 6) | ch
;
736 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
737 res
= (res
<< 6) | ch
;
738 if (res
< utf8_minval
[len
]) break;
746 static inline void read_skip( struct reader
*reader
, unsigned int count
)
748 while (reader
->read_pos
< reader
->read_size
&& count
)
755 static inline BOOL
read_isnamechar( unsigned int ch
)
757 /* FIXME: incomplete */
758 return (ch
>= 'A' && ch
<= 'Z') ||
759 (ch
>= 'a' && ch
<= 'z') ||
760 (ch
>= '0' && ch
<= '9') ||
761 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
764 static inline BOOL
read_isspace( unsigned int ch
)
766 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
769 static inline void read_skip_whitespace( struct reader
*reader
)
771 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
775 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
777 const char *ptr
= read_current_ptr( reader
);
779 if (len
< 0) len
= strlen( str
);
780 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
783 if (*str
!= *ptr
) return *ptr
- *str
;
789 static HRESULT
read_xmldecl( struct reader
*reader
)
791 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
793 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
795 reader
->state
= READER_STATE_BOF
;
798 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
799 read_skip( reader
, 6 );
801 /* FIXME: parse attributes */
802 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
805 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
806 read_skip( reader
, 2 );
808 reader
->state
= READER_STATE_BOF
;
812 static HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
814 if (elem
->attributeCount
)
816 WS_XML_ATTRIBUTE
**tmp
;
817 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
818 return E_OUTOFMEMORY
;
819 elem
->attributes
= tmp
;
821 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
822 elem
->attributes
[elem
->attributeCount
++] = attr
;
826 static HRESULT
read_attribute( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
828 WS_XML_ATTRIBUTE
*attr
;
829 WS_XML_UTF8_TEXT
*text
;
830 unsigned int len
= 0, ch
, skip
, quote
;
832 HRESULT hr
= WS_E_INVALID_FORMAT
;
834 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
836 start
= read_current_ptr( reader
);
839 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
840 if (!read_isnamechar( ch
)) break;
841 read_skip( reader
, skip
);
844 if (!len
) goto error
;
847 if (!(attr
->localName
= alloc_xml_string( start
, len
))) goto error
;
848 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 ))) goto error
;
849 attr
->prefix
->bytes
= NULL
;
850 if (!(attr
->ns
= alloc_xml_string( NULL
, 0 ))) goto error
;
851 attr
->ns
->bytes
= NULL
;
853 hr
= WS_E_INVALID_FORMAT
;
854 read_skip_whitespace( reader
);
855 if (read_cmp( reader
, "=", 1 )) goto error
;
856 read_skip( reader
, 1 );
858 read_skip_whitespace( reader
);
859 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) goto error
;
860 quote
= read_utf8_char( reader
, &skip
);
861 read_skip( reader
, 1 );
864 start
= read_current_ptr( reader
);
867 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
868 if (ch
== quote
) break;
869 read_skip( reader
, skip
);
872 read_skip( reader
, 1 );
874 if (!(text
= alloc_utf8_text( start
, len
)))
876 free_attribute( attr
);
877 return E_OUTOFMEMORY
;
879 attr
->value
= (WS_XML_TEXT
*)text
;
880 attr
->singleQuote
= (quote
== '\'');
886 free_attribute( attr
);
890 static HRESULT
read_element( struct reader
*reader
)
892 unsigned int len
= 0, ch
, skip
;
895 WS_XML_ELEMENT_NODE
*elem
;
896 WS_XML_ATTRIBUTE
*attr
;
897 HRESULT hr
= WS_E_INVALID_FORMAT
;
899 if (read_end_of_data( reader
))
901 struct list
*eof
= list_tail( &reader
->root
->children
);
902 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
903 reader
->state
= READER_STATE_EOF
;
907 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
908 elem
= (WS_XML_ELEMENT_NODE
*)node
;
910 if (read_cmp( reader
, "<", 1 )) goto error
;
911 read_skip( reader
, 1 );
913 start
= read_current_ptr( reader
);
916 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
917 if (!read_isnamechar( ch
)) break;
918 read_skip( reader
, skip
);
921 if (!len
) goto error
;
924 if (!(elem
->localName
= alloc_xml_string( start
, len
))) goto error
;
925 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 ))) goto error
;
926 elem
->prefix
->bytes
= NULL
;
927 if (!(elem
->ns
= alloc_xml_string( NULL
, 0 ))) goto error
;
931 read_skip_whitespace( reader
);
932 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
933 if ((hr
= read_attribute( reader
, &attr
)) != S_OK
) goto error
;
934 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
936 free_attribute( attr
);
941 read_skip_whitespace( reader
);
942 if (read_cmp( reader
, ">", 1 ) && read_cmp( reader
, "/>", 2 ))
944 hr
= WS_E_INVALID_FORMAT
;
948 read_insert_node( reader
, reader
->current
, node
);
949 if (!read_cmp( reader
, "/>", 2 ))
951 read_skip( reader
, 2 );
952 reader
->current
= reader
->current
->parent
;
953 reader
->state
= READER_STATE_STARTENDELEMENT
;
957 read_skip( reader
, 1 );
958 reader
->state
= READER_STATE_STARTELEMENT
;
967 static HRESULT
read_text( struct reader
*reader
)
969 unsigned int len
= 0, ch
, skip
;
972 WS_XML_TEXT_NODE
*text
;
973 WS_XML_UTF8_TEXT
*utf8
;
975 start
= read_current_ptr( reader
);
978 if (read_end_of_data( reader
)) break;
979 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
980 if (ch
== '<') break;
981 read_skip( reader
, skip
);
985 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
986 text
= (WS_XML_TEXT_NODE
*)node
;
987 if (!(utf8
= alloc_utf8_text( start
, len
)))
990 return E_OUTOFMEMORY
;
992 text
->text
= (WS_XML_TEXT
*)utf8
;
994 read_insert_node( reader
, reader
->current
, node
);
995 reader
->state
= READER_STATE_TEXT
;
999 static HRESULT
read_startelement( struct reader
*reader
)
1001 if (!read_cmp( reader
, "<", 1 )) return read_element( reader
);
1002 return read_text( reader
);
1005 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
1009 switch (reader
->state
)
1011 case READER_STATE_INITIAL
:
1012 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
1015 case READER_STATE_STARTELEMENT
:
1016 if (found
) *found
= TRUE
;
1023 read_skip_whitespace( reader
);
1024 if ((hr
= read_element( reader
)) == S_OK
&& found
)
1026 if (reader
->state
== READER_STATE_STARTELEMENT
)
1035 static BOOL
cmp_localname( const char *name1
, ULONG len1
, const char *name2
, ULONG len2
)
1038 if (len1
!= len2
) return FALSE
;
1039 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return FALSE
; }
1043 static struct node
*find_parent_element( struct node
*node
, const char *localname
, ULONG len
)
1045 struct node
*parent
;
1046 WS_XML_STRING
*name
;
1048 for (parent
= node
; parent
; parent
= parent
->parent
)
1050 if (parent
->hdr
.node
.nodeType
!= WS_XML_NODE_TYPE_ELEMENT
) continue;
1051 name
= ((WS_XML_ELEMENT_NODE
*)parent
)->localName
;
1052 if (!cmp_localname( (const char *)name
->bytes
, name
->length
, localname
, len
)) continue;
1058 static HRESULT
read_endelement( struct reader
*reader
)
1060 struct node
*node
, *parent
;
1061 unsigned int len
= 0, ch
, skip
;
1064 switch (reader
->state
)
1066 case READER_STATE_TEXT
:
1067 case READER_STATE_STARTELEMENT
:
1068 case READER_STATE_STARTENDELEMENT
:
1071 return WS_E_INVALID_FORMAT
;
1074 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
1075 read_skip( reader
, 2 );
1077 start
= read_current_ptr( reader
);
1080 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1083 read_skip( reader
, 1 );
1086 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
1087 read_skip( reader
, skip
);
1090 if (!(parent
= find_parent_element( reader
->current
, start
, len
)))
1091 return WS_E_INVALID_FORMAT
;
1093 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1094 read_insert_node( reader
, parent
, node
);
1095 reader
->state
= READER_STATE_ENDELEMENT
;
1099 static HRESULT
read_comment( struct reader
*reader
)
1101 unsigned int len
= 0, ch
, skip
;
1104 WS_XML_COMMENT_NODE
*comment
;
1106 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
1107 read_skip( reader
, 4 );
1109 start
= read_current_ptr( reader
);
1112 if (!read_cmp( reader
, "-->", 3 ))
1114 read_skip( reader
, 3 );
1117 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1118 read_skip( reader
, skip
);
1122 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
1123 comment
= (WS_XML_COMMENT_NODE
*)node
;
1124 if (!(comment
->value
.bytes
= heap_alloc( len
)))
1127 return E_OUTOFMEMORY
;
1129 memcpy( comment
->value
.bytes
, start
, len
);
1130 comment
->value
.length
= len
;
1132 read_insert_node( reader
, reader
->current
, node
);
1133 reader
->state
= READER_STATE_COMMENT
;
1137 static HRESULT
read_node( struct reader
*reader
)
1143 if (read_end_of_data( reader
))
1145 struct list
*eof
= list_tail( &reader
->root
->children
);
1146 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
1147 reader
->state
= READER_STATE_EOF
;
1150 if (!read_cmp( reader
, "<?", 2 ))
1152 hr
= read_xmldecl( reader
);
1153 if (FAILED( hr
)) return hr
;
1155 else if (!read_cmp( reader
, "</", 2 )) return read_endelement( reader
);
1156 else if (!read_cmp( reader
, "<!", 2 )) return read_comment( reader
);
1157 else if (!read_cmp( reader
, "<", 1 )) return read_startelement( reader
);
1158 else return read_text( reader
);
1162 /**************************************************************************
1163 * WsReadEndElement [webservices.@]
1165 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1167 struct reader
*reader
= (struct reader
*)handle
;
1169 TRACE( "%p %p\n", handle
, error
);
1170 if (error
) FIXME( "ignoring error parameter\n" );
1172 if (!reader
) return E_INVALIDARG
;
1173 return read_endelement( reader
);
1176 /**************************************************************************
1177 * WsReadNode [webservices.@]
1179 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
1181 struct reader
*reader
= (struct reader
*)handle
;
1183 TRACE( "%p %p\n", handle
, error
);
1184 if (error
) FIXME( "ignoring error parameter\n" );
1186 if (!reader
) return E_INVALIDARG
;
1187 return read_node( reader
);
1190 /**************************************************************************
1191 * WsReadStartElement [webservices.@]
1193 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1195 struct reader
*reader
= (struct reader
*)handle
;
1197 TRACE( "%p %p\n", handle
, error
);
1198 if (error
) FIXME( "ignoring error parameter\n" );
1200 if (!reader
) return E_INVALIDARG
;
1201 return read_startelement( reader
);
1204 /**************************************************************************
1205 * WsReadToStartElement [webservices.@]
1207 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
1208 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
1210 struct reader
*reader
= (struct reader
*)handle
;
1212 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
1213 if (error
) FIXME( "ignoring error parameter\n" );
1215 if (!reader
) return E_INVALIDARG
;
1216 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
1218 return read_to_startelement( reader
, found
);
1221 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
1224 BOOL success
= FALSE
;
1227 if (!read_end_of_data( reader
))
1229 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
1230 if (hr
!= S_OK
) return hr
;
1234 case WS_MOVE_TO_FIRST_NODE
:
1235 if ((ptr
= list_head( &reader
->current
->parent
->children
)))
1237 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1242 case WS_MOVE_TO_NEXT_NODE
:
1243 if ((ptr
= list_next( &reader
->current
->parent
->children
, &reader
->current
->entry
)))
1245 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1250 case WS_MOVE_TO_PREVIOUS_NODE
:
1251 if ((ptr
= list_prev( &reader
->current
->parent
->children
, &reader
->current
->entry
)))
1253 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1258 case WS_MOVE_TO_CHILD_NODE
:
1259 if ((ptr
= list_head( &reader
->current
->children
)))
1261 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1266 case WS_MOVE_TO_BOF
:
1267 reader
->current
= reader
->root
;
1271 case WS_MOVE_TO_EOF
:
1272 if ((ptr
= list_tail( &reader
->root
->children
)))
1274 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1280 FIXME( "unhandled move %u\n", move
);
1289 return success
? S_OK
: WS_E_INVALID_FORMAT
;
1292 /**************************************************************************
1293 * WsMoveReader [webservices.@]
1295 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
1297 struct reader
*reader
= (struct reader
*)handle
;
1299 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
1300 if (error
) FIXME( "ignoring error parameter\n" );
1302 if (!reader
) return E_INVALIDARG
;
1303 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
1305 return read_move_to( reader
, move
, found
);
1308 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
1312 switch (text
->textType
)
1314 case WS_XML_TEXT_TYPE_UTF8
:
1316 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1317 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
1318 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
1319 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
1324 FIXME( "unhandled type %u\n", text
->textType
);
1331 #define MAX_INT8 0x7f
1332 #define MIN_INT8 (-MAX_INT8 - 1)
1333 #define MAX_INT16 0x7fff
1334 #define MIN_INT16 (-MAX_INT16 - 1)
1335 #define MAX_INT32 0x7fffffff
1336 #define MIN_INT32 (-MAX_INT32 - 1)
1337 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1338 #define MIN_INT64 (-MAX_INT64 - 1)
1339 #define MAX_UINT8 0xff
1340 #define MAX_UINT16 0xffff
1341 #define MAX_UINT32 0xffffffff
1342 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1344 static HRESULT
str_to_int64( const char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
1346 BOOL negative
= FALSE
;
1347 const char *ptr
= str
;
1350 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
1351 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
1352 if (!len
) return WS_E_INVALID_FORMAT
;
1360 if (!len
) return WS_E_INVALID_FORMAT
;
1366 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
1368 if (negative
) val
= -val
;
1370 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
1371 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
1373 return WS_E_NUMERIC_OVERFLOW
;
1375 *ret
= *ret
* 10 + val
;
1382 static HRESULT
str_to_uint64( const char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
1384 const char *ptr
= str
;
1387 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
1388 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
1389 if (!len
) return WS_E_INVALID_FORMAT
;
1395 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
1398 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
1399 *ret
= *ret
* 10 + val
;
1406 /**************************************************************************
1407 * WsReadType [webservices.@]
1409 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1410 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
1411 ULONG value_size
, WS_ERROR
*error
)
1413 struct reader
*reader
= (struct reader
*)handle
;
1414 WS_XML_TEXT_NODE
*text
;
1416 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
1417 value_size
, error
);
1418 if (error
) FIXME( "ignoring error parameter\n" );
1420 if (!reader
|| !value
) return E_INVALIDARG
;
1422 if (reader
->current
->hdr
.node
.nodeType
!= WS_XML_NODE_TYPE_TEXT
)
1424 FIXME( "only text nodes are supported\n" );
1427 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
1428 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
1430 FIXME( "text type %u not supported\n", text
->text
->textType
);
1436 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1439 FIXME( "mapping %u not supported\n", mapping
);
1447 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1448 ULONG len
= utf8
->value
.length
;
1451 if (value_size
!= sizeof(BOOL
)) return E_INVALIDARG
;
1453 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) *ret
= TRUE
;
1454 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) *ret
= TRUE
;
1455 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) *ret
= FALSE
;
1456 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) *ret
= FALSE
;
1457 else return WS_E_INVALID_FORMAT
;
1462 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1467 if (value_size
!= sizeof(INT8
)) return E_INVALIDARG
;
1468 hr
= str_to_int64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
);
1469 if (hr
!= S_OK
) return hr
;
1475 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1480 if (value_size
!= sizeof(INT16
)) return E_INVALIDARG
;
1481 hr
= str_to_int64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
);
1482 if (hr
!= S_OK
) return hr
;
1488 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1493 if (value_size
!= sizeof(INT32
)) return E_INVALIDARG
;
1494 hr
= str_to_int64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
);
1495 if (hr
!= S_OK
) return hr
;
1501 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1502 INT64 val
, *ret
= value
;
1505 if (value_size
!= sizeof(INT64
)) return E_INVALIDARG
;
1506 hr
= str_to_int64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
);
1507 if (hr
!= S_OK
) return hr
;
1513 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1518 if (value_size
!= sizeof(UINT8
)) return E_INVALIDARG
;
1519 hr
= str_to_uint64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
);
1520 if (hr
!= S_OK
) return hr
;
1524 case WS_UINT16_TYPE
:
1526 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1527 UINT16
*ret
= value
;
1531 if (value_size
!= sizeof(UINT16
)) return E_INVALIDARG
;
1532 hr
= str_to_uint64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
);
1533 if (hr
!= S_OK
) return hr
;
1537 case WS_UINT32_TYPE
:
1539 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1540 UINT32
*ret
= value
;
1544 if (value_size
!= sizeof(UINT32
)) return E_INVALIDARG
;
1545 hr
= str_to_uint64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
);
1546 if (hr
!= S_OK
) return hr
;
1550 case WS_UINT64_TYPE
:
1552 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1553 UINT64 val
, *ret
= value
;
1556 if (value_size
!= sizeof(UINT64
)) return E_INVALIDARG
;
1557 hr
= str_to_uint64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
);
1558 if (hr
!= S_OK
) return hr
;
1564 WCHAR
*str
, **ret
= value
;
1566 if (value_size
!= sizeof(WCHAR
*)) return E_INVALIDARG
;
1567 if (!(str
= xmltext_to_widechar( heap
, text
->text
))) return E_OUTOFMEMORY
;
1572 FIXME( "type %u not supported\n", type
);
1579 /**************************************************************************
1580 * WsSetErrorProperty [webservices.@]
1582 HRESULT WINAPI
WsSetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, const void *value
,
1585 struct error
*error
= (struct error
*)handle
;
1587 TRACE( "%p %u %p %u\n", handle
, id
, value
, size
);
1589 if (id
== WS_ERROR_PROPERTY_LANGID
) return WS_E_INVALID_OPERATION
;
1590 return set_error_prop( error
, id
, value
, size
);
1593 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
1595 static const char bom
[] = {0xef,0xbb,0xbf};
1596 const unsigned char *p
= data
;
1598 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
1599 (size
> 2 && !(*offset
= 0));
1602 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
1604 static const char bom
[] = {0xff,0xfe};
1605 const unsigned char *p
= data
;
1607 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
1608 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
1611 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
1615 /* FIXME: parse xml declaration */
1617 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
1618 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
1621 FIXME( "charset not recognized\n" );
1625 TRACE( "detected charset %u\n", ret
);
1629 static void set_input_buffer( struct reader
*reader
, const char *data
, ULONG size
)
1631 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
1632 reader
->input_data
= data
;
1633 reader
->input_size
= size
;
1635 reader
->read_size
= reader
->input_size
;
1636 reader
->read_pos
= 0;
1637 reader
->read_bufptr
= reader
->input_data
;
1640 /**************************************************************************
1641 * WsSetInput [webservices.@]
1643 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
1644 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
1645 ULONG count
, WS_ERROR
*error
)
1647 struct reader
*reader
= (struct reader
*)handle
;
1650 ULONG i
, offset
= 0;
1652 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
1653 if (error
) FIXME( "ignoring error parameter\n" );
1655 if (!reader
) return E_INVALIDARG
;
1657 for (i
= 0; i
< count
; i
++)
1659 hr
= set_reader_prop( reader
, properties
[i
].id
, properties
[i
].value
, properties
[i
].valueSize
);
1660 if (hr
!= S_OK
) return hr
;
1663 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
1665 switch (encoding
->encodingType
)
1667 case WS_XML_READER_ENCODING_TYPE_TEXT
:
1669 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
1670 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
1671 WS_CHARSET charset
= text
->charSet
;
1673 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
1675 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
1679 if (charset
== WS_CHARSET_AUTO
)
1680 charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
1682 hr
= set_reader_prop( reader
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
1683 if (hr
!= S_OK
) return hr
;
1687 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
1690 switch (input
->inputType
)
1692 case WS_XML_READER_INPUT_TYPE_BUFFER
:
1694 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
1695 set_input_buffer( reader
, (const char *)buf
->encodedData
+ offset
, buf
->encodedDataSize
- offset
);
1699 FIXME( "input type %u not supported\n", input
->inputType
);
1703 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
1704 read_insert_bof( reader
, node
);
1708 /**************************************************************************
1709 * WsSetInputToBuffer [webservices.@]
1711 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
1712 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
1715 struct reader
*reader
= (struct reader
*)handle
;
1716 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1720 ULONG i
, offset
= 0;
1722 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
1723 if (error
) FIXME( "ignoring error parameter\n" );
1725 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
1727 for (i
= 0; i
< count
; i
++)
1729 hr
= set_reader_prop( reader
, properties
[i
].id
, properties
[i
].value
, properties
[i
].valueSize
);
1730 if (hr
!= S_OK
) return hr
;
1733 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
1735 charset
= detect_charset( xmlbuf
->ptr
, xmlbuf
->size
, &offset
);
1736 hr
= set_reader_prop( reader
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
1737 if (hr
!= S_OK
) return hr
;
1739 set_input_buffer( reader
, (const char *)xmlbuf
->ptr
+ offset
, xmlbuf
->size
- offset
);
1740 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
1741 read_insert_bof( reader
, node
);
1745 /**************************************************************************
1746 * WsXmlStringEquals [webservices.@]
1748 HRESULT WINAPI
WsXmlStringEquals( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
, WS_ERROR
*error
)
1750 TRACE( "%s %s %p\n", debugstr_xmlstr(str1
), debugstr_xmlstr(str2
), error
);
1751 if (error
) FIXME( "ignoring error parameter\n" );
1753 if (!str1
|| !str2
) return E_INVALIDARG
;
1755 if (str1
->length
!= str2
->length
) return S_FALSE
;
1756 if (!memcmp( str1
->bytes
, str2
->bytes
, str1
->length
)) return S_OK
;