2 * Copyright 2015, 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "webservices_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
32 const char *debugstr_xmlstr( const WS_XML_STRING
*str
)
34 if (!str
) return "(null)";
35 return debugstr_an( (const char *)str
->bytes
, str
->length
);
38 ULONG
prop_size( const struct prop_desc
*desc
, ULONG count
)
40 ULONG i
, ret
= count
* sizeof(struct prop
);
41 for (i
= 0; i
< count
; i
++) ret
+= desc
[i
].size
;
45 void prop_init( const struct prop_desc
*desc
, ULONG count
, struct prop
*prop
, void *data
)
49 for (i
= 0; i
< count
; i
++)
52 prop
[i
].size
= desc
[i
].size
;
53 prop
[i
].readonly
= desc
[i
].readonly
;
54 prop
[i
].writeonly
= desc
[i
].writeonly
;
59 HRESULT
prop_set( const struct prop
*prop
, ULONG count
, ULONG id
, const void *value
, ULONG size
)
61 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].readonly
) return E_INVALIDARG
;
62 memcpy( prop
[id
].value
, value
, size
);
66 HRESULT
prop_get( const struct prop
*prop
, ULONG count
, ULONG id
, void *buf
, ULONG size
)
68 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].writeonly
) return E_INVALIDARG
;
69 memcpy( buf
, prop
[id
].value
, prop
[id
].size
);
73 static const struct prop_desc error_props
[] =
75 { sizeof(ULONG
), TRUE
}, /* WS_ERROR_PROPERTY_STRING_COUNT */
76 { sizeof(ULONG
), FALSE
}, /* WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE */
77 { sizeof(LANGID
), FALSE
} /* WS_ERROR_PROPERTY_LANGID */
83 struct prop prop
[sizeof(error_props
)/sizeof(error_props
[0])];
86 static struct error
*alloc_error(void)
88 static const ULONG count
= sizeof(error_props
)/sizeof(error_props
[0]);
90 ULONG size
= sizeof(*ret
) + prop_size( error_props
, count
);
92 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
93 prop_init( error_props
, count
, ret
->prop
, &ret
[1] );
94 ret
->prop_count
= count
;
98 /**************************************************************************
99 * WsCreateError [webservices.@]
101 HRESULT WINAPI
WsCreateError( const WS_ERROR_PROPERTY
*properties
, ULONG count
, WS_ERROR
**handle
)
104 LANGID langid
= GetUserDefaultUILanguage();
108 TRACE( "%p %u %p\n", properties
, count
, handle
);
110 if (!handle
) return E_INVALIDARG
;
111 if (!(error
= alloc_error())) return E_OUTOFMEMORY
;
113 prop_set( error
->prop
, error
->prop_count
, WS_ERROR_PROPERTY_LANGID
, &langid
, sizeof(langid
) );
114 for (i
= 0; i
< count
; i
++)
116 if (properties
[i
].id
== WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE
)
121 hr
= prop_set( error
->prop
, error
->prop_count
, properties
[i
].id
, properties
[i
].value
,
122 properties
[i
].valueSize
);
130 *handle
= (WS_ERROR
*)error
;
134 /**************************************************************************
135 * WsFreeError [webservices.@]
137 void WINAPI
WsFreeError( WS_ERROR
*handle
)
139 struct error
*error
= (struct error
*)handle
;
141 TRACE( "%p\n", handle
);
145 /**************************************************************************
146 * WsResetError [webservices.@]
148 HRESULT WINAPI
WsResetError( WS_ERROR
*handle
)
150 struct error
*error
= (struct error
*)handle
;
153 TRACE( "%p\n", handle
);
155 if (!handle
) return E_INVALIDARG
;
157 /* FIXME: release strings added with WsAddErrorString when it's implemented, reset string count */
159 return prop_set( error
->prop
, error
->prop_count
, WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE
, &code
, sizeof(code
) );
162 static const struct prop_desc heap_props
[] =
164 { sizeof(SIZE_T
), FALSE
}, /* WS_HEAP_PROPERTY_MAX_SIZE */
165 { sizeof(SIZE_T
), FALSE
}, /* WS_HEAP_PROPERTY_TRIM_SIZE */
166 { sizeof(SIZE_T
), TRUE
}, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
167 { sizeof(SIZE_T
), TRUE
} /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
174 struct prop prop
[sizeof(heap_props
)/sizeof(heap_props
[0])];
177 static BOOL
ensure_heap( struct heap
*heap
)
180 if (heap
->handle
) return TRUE
;
181 if (prop_get( heap
->prop
, heap
->prop_count
, WS_HEAP_PROPERTY_MAX_SIZE
, &size
, sizeof(size
) ) != S_OK
)
183 if (!(heap
->handle
= HeapCreate( 0, 0, size
))) return FALSE
;
187 void *ws_alloc( WS_HEAP
*handle
, SIZE_T size
)
189 struct heap
*heap
= (struct heap
*)handle
;
190 if (!ensure_heap( heap
)) return NULL
;
191 return HeapAlloc( heap
->handle
, 0, size
);
194 static void *ws_alloc_zero( WS_HEAP
*handle
, SIZE_T size
)
196 struct heap
*heap
= (struct heap
*)handle
;
197 if (!ensure_heap( heap
)) return NULL
;
198 return HeapAlloc( heap
->handle
, HEAP_ZERO_MEMORY
, size
);
201 void *ws_realloc( WS_HEAP
*handle
, void *ptr
, SIZE_T size
)
203 struct heap
*heap
= (struct heap
*)handle
;
204 if (!ensure_heap( heap
)) return NULL
;
205 return HeapReAlloc( heap
->handle
, 0, ptr
, size
);
208 static void *ws_realloc_zero( WS_HEAP
*handle
, void *ptr
, SIZE_T size
)
210 struct heap
*heap
= (struct heap
*)handle
;
211 if (!ensure_heap( heap
)) return NULL
;
212 return HeapReAlloc( heap
->handle
, HEAP_ZERO_MEMORY
, ptr
, size
);
215 void ws_free( WS_HEAP
*handle
, void *ptr
)
217 struct heap
*heap
= (struct heap
*)handle
;
218 if (!heap
->handle
) return;
219 HeapFree( heap
->handle
, 0, ptr
);
222 /**************************************************************************
223 * WsAlloc [webservices.@]
225 HRESULT WINAPI
WsAlloc( WS_HEAP
*handle
, SIZE_T size
, void **ptr
, WS_ERROR
*error
)
229 TRACE( "%p %u %p %p\n", handle
, (ULONG
)size
, ptr
, error
);
230 if (error
) FIXME( "ignoring error parameter\n" );
232 if (!handle
|| !ptr
) return E_INVALIDARG
;
234 if (!(mem
= ws_alloc( handle
, size
))) return E_OUTOFMEMORY
;
239 static struct heap
*alloc_heap(void)
241 static const ULONG count
= sizeof(heap_props
)/sizeof(heap_props
[0]);
243 ULONG size
= sizeof(*ret
) + prop_size( heap_props
, count
);
245 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
246 prop_init( heap_props
, count
, ret
->prop
, &ret
[1] );
247 ret
->prop_count
= count
;
251 /**************************************************************************
252 * WsCreateHeap [webservices.@]
254 HRESULT WINAPI
WsCreateHeap( SIZE_T max_size
, SIZE_T trim_size
, const WS_HEAP_PROPERTY
*properties
,
255 ULONG count
, WS_HEAP
**handle
, WS_ERROR
*error
)
259 TRACE( "%u %u %p %u %p %p\n", (ULONG
)max_size
, (ULONG
)trim_size
, properties
, count
, handle
, error
);
260 if (error
) FIXME( "ignoring error parameter\n" );
262 if (!handle
|| count
) return E_INVALIDARG
;
263 if (!(heap
= alloc_heap())) return E_OUTOFMEMORY
;
265 prop_set( heap
->prop
, heap
->prop_count
, WS_HEAP_PROPERTY_MAX_SIZE
, &max_size
, sizeof(max_size
) );
266 prop_set( heap
->prop
, heap
->prop_count
, WS_HEAP_PROPERTY_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
268 *handle
= (WS_HEAP
*)heap
;
272 /**************************************************************************
273 * WsFreeHeap [webservices.@]
275 void WINAPI
WsFreeHeap( WS_HEAP
*handle
)
277 struct heap
*heap
= (struct heap
*)handle
;
279 TRACE( "%p\n", handle
);
282 HeapDestroy( heap
->handle
);
286 /**************************************************************************
287 * WsResetHeap [webservices.@]
289 HRESULT WINAPI
WsResetHeap( WS_HEAP
*handle
, WS_ERROR
*error
)
291 struct heap
*heap
= (struct heap
*)handle
;
293 TRACE( "%p %p\n", handle
, error
);
294 if (error
) FIXME( "ignoring error parameter\n" );
296 if (!heap
) return E_INVALIDARG
;
298 HeapDestroy( heap
->handle
);
303 struct node
*alloc_node( WS_XML_NODE_TYPE type
)
307 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
308 ret
->hdr
.node
.nodeType
= type
;
309 list_init( &ret
->entry
);
310 list_init( &ret
->children
);
314 void free_attribute( WS_XML_ATTRIBUTE
*attr
)
317 heap_free( attr
->prefix
);
318 heap_free( attr
->localName
);
319 heap_free( attr
->ns
);
320 heap_free( attr
->value
);
324 void free_node( struct node
*node
)
327 switch (node_type( node
))
329 case WS_XML_NODE_TYPE_ELEMENT
:
331 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
334 for (i
= 0; i
< elem
->attributeCount
; i
++) free_attribute( elem
->attributes
[i
] );
335 heap_free( elem
->attributes
);
336 heap_free( elem
->prefix
);
337 heap_free( elem
->localName
);
338 heap_free( elem
->ns
);
341 case WS_XML_NODE_TYPE_TEXT
:
343 WS_XML_TEXT_NODE
*text
= (WS_XML_TEXT_NODE
*)node
;
344 heap_free( text
->text
);
347 case WS_XML_NODE_TYPE_COMMENT
:
349 WS_XML_COMMENT_NODE
*comment
= (WS_XML_COMMENT_NODE
*)node
;
350 heap_free( comment
->value
.bytes
);
353 case WS_XML_NODE_TYPE_CDATA
:
354 case WS_XML_NODE_TYPE_END_CDATA
:
355 case WS_XML_NODE_TYPE_END_ELEMENT
:
356 case WS_XML_NODE_TYPE_EOF
:
357 case WS_XML_NODE_TYPE_BOF
:
361 ERR( "unhandled type %u\n", node_type( node
) );
367 void destroy_nodes( struct node
*node
)
372 while ((ptr
= list_head( &node
->children
)))
374 struct node
*child
= LIST_ENTRY( ptr
, struct node
, entry
);
375 list_remove( &child
->entry
);
376 destroy_nodes( child
);
381 static WS_XML_ATTRIBUTE
*dup_attribute( const WS_XML_ATTRIBUTE
*src
)
383 WS_XML_ATTRIBUTE
*dst
;
384 const WS_XML_STRING
*prefix
= (src
->prefix
&& src
->prefix
->length
) ? src
->prefix
: NULL
;
385 const WS_XML_STRING
*localname
= src
->localName
;
386 const WS_XML_STRING
*ns
= src
->localName
;
388 if (!(dst
= heap_alloc( sizeof(*dst
) ))) return NULL
;
389 dst
->singleQuote
= src
->singleQuote
;
390 dst
->isXmlNs
= src
->isXmlNs
;
391 if (prefix
&& !(dst
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
))) goto error
;
392 if (localname
&& !(dst
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
))) goto error
;
393 if (ns
&& !(dst
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) goto error
;
397 free_attribute( dst
);
401 static WS_XML_ATTRIBUTE
**dup_attributes( WS_XML_ATTRIBUTE
* const *src
, ULONG count
)
403 WS_XML_ATTRIBUTE
**dst
;
406 if (!(dst
= heap_alloc( sizeof(*dst
) * count
))) return NULL
;
407 for (i
= 0; i
< count
; i
++)
409 if (!(dst
[i
] = dup_attribute( src
[i
] )))
411 for (; i
> 0; i
--) free_attribute( dst
[i
- 1] );
419 static struct node
*dup_element_node( const WS_XML_ELEMENT_NODE
*src
)
422 WS_XML_ELEMENT_NODE
*dst
;
423 ULONG count
= src
->attributeCount
;
424 WS_XML_ATTRIBUTE
**attrs
= src
->attributes
;
425 const WS_XML_STRING
*prefix
= (src
->prefix
&& src
->prefix
->length
) ? src
->prefix
: NULL
;
426 const WS_XML_STRING
*localname
= src
->localName
;
427 const WS_XML_STRING
*ns
= src
->ns
;
429 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
432 if (count
&& !(dst
->attributes
= dup_attributes( attrs
, count
))) goto error
;
433 dst
->attributeCount
= count
;
435 if (prefix
&& !(dst
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
))) goto error
;
436 if (localname
&& !(dst
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
))) goto error
;
437 if (ns
&& !(dst
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) goto error
;
445 static struct node
*dup_text_node( const WS_XML_TEXT_NODE
*src
)
448 WS_XML_TEXT_NODE
*dst
;
450 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
451 dst
= (WS_XML_TEXT_NODE
*)node
;
455 WS_XML_UTF8_TEXT
*utf8
;
456 const WS_XML_UTF8_TEXT
*utf8_src
= (WS_XML_UTF8_TEXT
*)src
->text
;
457 if (!(utf8
= alloc_utf8_text( utf8_src
->value
.bytes
, utf8_src
->value
.length
)))
462 dst
->text
= &utf8
->text
;
467 static struct node
*dup_comment_node( const WS_XML_COMMENT_NODE
*src
)
470 WS_XML_COMMENT_NODE
*dst
;
472 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return NULL
;
473 dst
= (WS_XML_COMMENT_NODE
*)node
;
475 if (src
->value
.length
&& !(dst
->value
.bytes
= heap_alloc( src
->value
.length
)))
480 memcpy( dst
->value
.bytes
, src
->value
.bytes
, src
->value
.length
);
481 dst
->value
.length
= src
->value
.length
;
485 static struct node
*dup_node( const struct node
*src
)
487 switch (node_type( src
))
489 case WS_XML_NODE_TYPE_ELEMENT
:
490 return dup_element_node( &src
->hdr
);
492 case WS_XML_NODE_TYPE_TEXT
:
493 return dup_text_node( (const WS_XML_TEXT_NODE
*)src
);
495 case WS_XML_NODE_TYPE_COMMENT
:
496 return dup_comment_node( (const WS_XML_COMMENT_NODE
*)src
);
498 case WS_XML_NODE_TYPE_CDATA
:
499 case WS_XML_NODE_TYPE_END_CDATA
:
500 case WS_XML_NODE_TYPE_END_ELEMENT
:
501 case WS_XML_NODE_TYPE_EOF
:
502 case WS_XML_NODE_TYPE_BOF
:
503 return alloc_node( node_type( src
) );
506 ERR( "unhandled type %u\n", node_type( src
) );
512 static HRESULT
dup_tree( struct node
**dst
, const struct node
*src
)
515 const struct node
*child
;
517 if (!*dst
&& !(*dst
= dup_node( src
))) return E_OUTOFMEMORY
;
520 LIST_FOR_EACH_ENTRY( child
, &src
->children
, struct node
, entry
)
522 HRESULT hr
= E_OUTOFMEMORY
;
523 struct node
*new_child
;
525 if (!(new_child
= dup_node( child
)) || (hr
= dup_tree( &new_child
, child
)) != S_OK
)
527 destroy_nodes( *dst
);
530 new_child
->parent
= parent
;
531 list_add_tail( &parent
->children
, &new_child
->entry
);
536 static const struct prop_desc reader_props
[] =
538 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
539 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
540 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
541 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
542 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
543 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
544 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
545 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
546 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
547 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
548 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
549 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
550 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
551 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
552 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
557 READER_STATE_INITIAL
,
559 READER_STATE_STARTELEMENT
,
560 READER_STATE_STARTATTRIBUTE
,
561 READER_STATE_STARTCDATA
,
564 READER_STATE_ENDELEMENT
,
565 READER_STATE_ENDCDATA
,
566 READER_STATE_COMMENT
,
580 const unsigned char *read_bufptr
;
581 enum reader_state state
;
583 struct node
*current
;
586 struct prefix
*prefixes
;
588 ULONG nb_prefixes_allocated
;
589 WS_XML_READER_INPUT_TYPE input_type
;
590 struct xmlbuf
*input_buf
;
591 const unsigned char *input_data
;
594 struct prop prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
597 static struct reader
*alloc_reader(void)
599 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
601 ULONG size
= sizeof(*ret
) + prop_size( reader_props
, count
);
603 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
604 if (!(ret
->prefixes
= heap_alloc_zero( sizeof(*ret
->prefixes
) )))
609 ret
->nb_prefixes
= ret
->nb_prefixes_allocated
= 1;
611 prop_init( reader_props
, count
, ret
->prop
, &ret
[1] );
612 ret
->prop_count
= count
;
616 static void clear_prefixes( struct prefix
*prefixes
, ULONG count
)
619 for (i
= 0; i
< count
; i
++)
621 heap_free( prefixes
[i
].str
.bytes
);
622 prefixes
[i
].str
.bytes
= NULL
;
623 prefixes
[i
].str
.length
= 0;
625 heap_free( prefixes
[i
].ns
.bytes
);
626 prefixes
[i
].ns
.bytes
= NULL
;
627 prefixes
[i
].ns
.length
= 0;
631 static void free_reader( struct reader
*reader
)
634 destroy_nodes( reader
->root
);
635 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
636 heap_free( reader
->prefixes
);
640 HRESULT
copy_node( WS_XML_READER
*handle
, struct node
**node
)
642 struct reader
*reader
= (struct reader
*)handle
;
643 return dup_tree( node
, reader
->current
);
646 static HRESULT
set_prefix( struct prefix
*prefix
, const WS_XML_STRING
*str
, const WS_XML_STRING
*ns
)
650 heap_free( prefix
->str
.bytes
);
651 if (!(prefix
->str
.bytes
= heap_alloc( str
->length
))) return E_OUTOFMEMORY
;
652 memcpy( prefix
->str
.bytes
, str
->bytes
, str
->length
);
653 prefix
->str
.length
= str
->length
;
656 heap_free( prefix
->ns
.bytes
);
657 if (!(prefix
->ns
.bytes
= heap_alloc( ns
->length
))) return E_OUTOFMEMORY
;
658 memcpy( prefix
->ns
.bytes
, ns
->bytes
, ns
->length
);
659 prefix
->ns
.length
= ns
->length
;
664 static HRESULT
bind_prefix( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
*ns
)
669 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
671 if (WsXmlStringEquals( prefix
, &reader
->prefixes
[i
].str
, NULL
) == S_OK
)
672 return set_prefix( &reader
->prefixes
[i
], NULL
, ns
);
674 if (i
>= reader
->nb_prefixes_allocated
)
676 ULONG new_size
= reader
->nb_prefixes_allocated
* sizeof(*reader
->prefixes
) * 2;
677 struct prefix
*tmp
= heap_realloc_zero( reader
->prefixes
, new_size
);
678 if (!tmp
) return E_OUTOFMEMORY
;
679 reader
->prefixes
= tmp
;
680 reader
->nb_prefixes_allocated
*= 2;
683 if ((hr
= set_prefix( &reader
->prefixes
[i
], prefix
, ns
)) != S_OK
) return hr
;
684 reader
->nb_prefixes
++;
688 static const WS_XML_STRING
*get_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
)
691 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
693 if (WsXmlStringEquals( prefix
, &reader
->prefixes
[i
].str
, NULL
) == S_OK
)
694 return &reader
->prefixes
[i
].ns
;
699 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
701 if (!reader
->root
) reader
->root
= eof
;
704 eof
->parent
= reader
->root
;
705 list_add_tail( &reader
->root
->children
, &eof
->entry
);
707 reader
->current
= reader
->last
= eof
;
710 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
712 reader
->root
->parent
= bof
;
713 list_add_tail( &bof
->children
, &reader
->root
->entry
);
714 reader
->current
= reader
->last
= reader
->root
= bof
;
717 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
719 node
->parent
= parent
;
720 list_add_before( list_tail( &parent
->children
), &node
->entry
);
721 reader
->current
= reader
->last
= node
;
724 static HRESULT
read_init_state( struct reader
*reader
)
728 destroy_nodes( reader
->root
);
730 reader
->input_buf
= NULL
;
731 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
732 reader
->nb_prefixes
= 1;
733 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
734 read_insert_eof( reader
, node
);
735 reader
->state
= READER_STATE_INITIAL
;
739 /**************************************************************************
740 * WsCreateReader [webservices.@]
742 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
743 WS_XML_READER
**handle
, WS_ERROR
*error
)
745 struct reader
*reader
;
746 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
747 WS_CHARSET charset
= WS_CHARSET_UTF8
;
748 BOOL read_decl
= TRUE
;
751 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
752 if (error
) FIXME( "ignoring error parameter\n" );
754 if (!handle
) return E_INVALIDARG
;
755 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
757 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
758 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
759 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
760 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
761 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
763 for (i
= 0; i
< count
; i
++)
765 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
766 properties
[i
].valueSize
);
769 free_reader( reader
);
774 if ((hr
= read_init_state( reader
)) != S_OK
)
776 free_reader( reader
);
780 *handle
= (WS_XML_READER
*)reader
;
784 /**************************************************************************
785 * WsFreeReader [webservices.@]
787 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
789 struct reader
*reader
= (struct reader
*)handle
;
791 TRACE( "%p\n", handle
);
792 free_reader( reader
);
795 /**************************************************************************
796 * WsFillReader [webservices.@]
798 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
801 struct reader
*reader
= (struct reader
*)handle
;
803 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
804 if (error
) FIXME( "ignoring error parameter\n" );
806 if (!reader
) return E_INVALIDARG
;
808 /* FIXME: add support for stream input */
809 reader
->read_size
= min( min_size
, reader
->input_size
);
810 reader
->read_pos
= 0;
815 /**************************************************************************
816 * WsGetErrorProperty [webservices.@]
818 HRESULT WINAPI
WsGetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, void *buf
,
821 struct error
*error
= (struct error
*)handle
;
823 TRACE( "%p %u %p %u\n", handle
, id
, buf
, size
);
824 return prop_get( error
->prop
, error
->prop_count
, id
, buf
, size
);
827 /**************************************************************************
828 * WsGetErrorString [webservices.@]
830 HRESULT WINAPI
WsGetErrorString( WS_ERROR
*handle
, ULONG index
, WS_STRING
*str
)
832 FIXME( "%p %u %p: stub\n", handle
, index
, str
);
836 /**************************************************************************
837 * WsGetHeapProperty [webservices.@]
839 HRESULT WINAPI
WsGetHeapProperty( WS_HEAP
*handle
, WS_HEAP_PROPERTY_ID id
, void *buf
,
840 ULONG size
, WS_ERROR
*error
)
842 struct heap
*heap
= (struct heap
*)handle
;
844 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
845 if (error
) FIXME( "ignoring error parameter\n" );
847 return prop_get( heap
->prop
, heap
->prop_count
, id
, buf
, size
);
850 /**************************************************************************
851 * WsGetNamespaceFromPrefix [webservices.@]
853 HRESULT WINAPI
WsGetNamespaceFromPrefix( WS_XML_READER
*handle
, const WS_XML_STRING
*prefix
,
854 BOOL required
, const WS_XML_STRING
**ns
, WS_ERROR
*error
)
856 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
857 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
858 static const WS_XML_STRING empty_ns
= {0, NULL
};
859 static const WS_XML_STRING xml_ns
= {36, (BYTE
*)"http://www.w3.org/XML/1998/namespace"};
860 static const WS_XML_STRING xmlns_ns
= {29, (BYTE
*)"http://www.w3.org/2000/xmlns/"};
861 struct reader
*reader
= (struct reader
*)handle
;
864 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(prefix
), required
, ns
, error
);
865 if (error
) FIXME( "ignoring error parameter\n" );
867 if (!reader
|| !prefix
|| !ns
) return E_INVALIDARG
;
868 if (reader
->state
!= READER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
875 else if (WsXmlStringEquals( prefix
, &xml
, NULL
) == S_OK
)
880 else if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
887 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
890 for (i
= 0; i
< elem
->attributeCount
; i
++)
892 if (!elem
->attributes
[i
]->isXmlNs
) continue;
893 if (WsXmlStringEquals( prefix
, elem
->attributes
[i
]->prefix
, NULL
) == S_OK
)
895 *ns
= elem
->attributes
[i
]->ns
;
904 if (required
) return WS_E_INVALID_FORMAT
;
911 /**************************************************************************
912 * WsGetReaderNode [webservices.@]
914 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
917 struct reader
*reader
= (struct reader
*)handle
;
919 TRACE( "%p %p %p\n", handle
, node
, error
);
920 if (error
) FIXME( "ignoring error parameter\n" );
922 if (!reader
|| !node
) return E_INVALIDARG
;
924 *node
= &reader
->current
->hdr
.node
;
928 /**************************************************************************
929 * WsGetReaderProperty [webservices.@]
931 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
932 void *buf
, ULONG size
, WS_ERROR
*error
)
934 struct reader
*reader
= (struct reader
*)handle
;
936 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
937 if (error
) FIXME( "ignoring error parameter\n" );
939 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
941 if (id
== WS_XML_READER_PROPERTY_CHARSET
)
946 if ((hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, &charset
, size
)) != S_OK
) return hr
;
947 if (!charset
) return WS_E_INVALID_FORMAT
;
948 *(WS_CHARSET
*)buf
= charset
;
951 return prop_get( reader
->prop
, reader
->prop_count
, id
, buf
, size
);
954 /**************************************************************************
955 * WsGetXmlAttribute [webservices.@]
957 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
958 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
960 FIXME( "%p %s %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
964 WS_XML_STRING
*alloc_xml_string( const unsigned char *data
, ULONG len
)
968 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
970 ret
->bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
971 ret
->dictionary
= NULL
;
973 if (data
) memcpy( ret
->bytes
, data
, len
);
977 WS_XML_UTF8_TEXT
*alloc_utf8_text( const unsigned char *data
, ULONG len
)
979 WS_XML_UTF8_TEXT
*ret
;
981 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
982 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
983 ret
->value
.length
= len
;
984 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
985 ret
->value
.dictionary
= NULL
;
987 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
991 static inline BOOL
read_end_of_data( struct reader
*reader
)
993 return reader
->read_pos
>= reader
->read_size
;
996 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
998 return &reader
->read_bufptr
[reader
->read_pos
];
1001 /* UTF-8 support based on libs/wine/utf8.c */
1003 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
1004 static const char utf8_length
[128] =
1006 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
1007 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
1008 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
1009 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
1010 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
1011 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
1012 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
1013 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
1016 /* first byte mask depending on UTF-8 sequence length */
1017 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
1019 /* minimum Unicode value depending on UTF-8 sequence length */
1020 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
1022 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
1024 unsigned int len
, res
;
1025 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
1026 const unsigned char *end
;
1028 if (reader
->read_pos
>= reader
->read_size
) return 0;
1035 len
= utf8_length
[ch
- 0x80];
1036 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
1037 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
;
1038 res
= ch
& utf8_mask
[len
];
1043 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
1044 res
= (res
<< 6) | ch
;
1046 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
1047 res
= (res
<< 6) | ch
;
1049 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
1050 res
= (res
<< 6) | ch
;
1051 if (res
< utf8_minval
[len
]) break;
1059 static inline void read_skip( struct reader
*reader
, unsigned int count
)
1061 if (reader
->read_pos
+ count
> reader
->read_size
) return;
1062 reader
->read_pos
+= count
;
1065 static inline void read_rewind( struct reader
*reader
, unsigned int count
)
1067 reader
->read_pos
-= count
;
1070 static inline BOOL
read_isnamechar( unsigned int ch
)
1072 /* FIXME: incomplete */
1073 return (ch
>= 'A' && ch
<= 'Z') ||
1074 (ch
>= 'a' && ch
<= 'z') ||
1075 (ch
>= '0' && ch
<= '9') ||
1076 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
1079 static inline BOOL
read_isspace( unsigned int ch
)
1081 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
1084 static inline void read_skip_whitespace( struct reader
*reader
)
1086 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
1090 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
1092 const unsigned char *ptr
= read_current_ptr( reader
);
1094 if (len
< 0) len
= strlen( str
);
1095 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
1098 if (*str
!= *ptr
) return *ptr
- *str
;
1104 static HRESULT
read_xmldecl( struct reader
*reader
)
1106 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
1108 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
1110 reader
->state
= READER_STATE_BOF
;
1113 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
1114 read_skip( reader
, 6 );
1116 /* FIXME: parse attributes */
1117 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
1120 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
1121 read_skip( reader
, 2 );
1123 reader
->state
= READER_STATE_BOF
;
1127 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
1129 if (elem
->attributeCount
)
1131 WS_XML_ATTRIBUTE
**tmp
;
1132 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
1133 return E_OUTOFMEMORY
;
1134 elem
->attributes
= tmp
;
1136 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
1137 elem
->attributes
[elem
->attributeCount
++] = attr
;
1141 static HRESULT
parse_name( const unsigned char *str
, unsigned int len
,
1142 WS_XML_STRING
**prefix
, WS_XML_STRING
**localname
)
1144 const unsigned char *name_ptr
= str
, *prefix_ptr
= NULL
;
1145 unsigned int i
, name_len
= len
, prefix_len
= 0;
1147 for (i
= 0; i
< len
; i
++)
1153 name_ptr
= &str
[i
+ 1];
1158 if (!(*prefix
= alloc_xml_string( prefix_ptr
, prefix_len
))) return E_OUTOFMEMORY
;
1159 if (!(*localname
= alloc_xml_string( name_ptr
, name_len
)))
1161 heap_free( *prefix
);
1162 return E_OUTOFMEMORY
;
1167 static int codepoint_to_utf8( int cp
, unsigned char *dst
)
1178 dst
[1] = 0x80 | (cp
& 0x3f);
1183 if ((cp
>= 0xd800 && cp
<= 0xdfff) || cp
== 0xfffe || cp
== 0xffff) return -1;
1186 dst
[2] = 0x80 | (cp
& 0x3f);
1188 dst
[1] = 0x80 | (cp
& 0x3f);
1193 if (cp
>= 0x110000) return -1;
1194 dst
[3] = 0x80 | (cp
& 0x3f);
1196 dst
[2] = 0x80 | (cp
& 0x3f);
1198 dst
[1] = 0x80 | (cp
& 0x3f);
1204 static HRESULT
decode_text( const unsigned char *str
, ULONG len
, unsigned char *ret
, ULONG
*ret_len
)
1206 const unsigned char *p
= str
;
1207 unsigned char *q
= ret
;
1215 if (!len
) return WS_E_INVALID_FORMAT
;
1217 if (len
>= 3 && !memcmp( p
, "lt;", 3 ))
1223 else if (len
>= 3 && !memcmp( p
, "gt;", 3 ))
1229 else if (len
>= 5 && !memcmp( p
, "quot;", 5 ))
1235 else if (len
>= 4 && !memcmp( p
, "amp;", 4 ))
1241 else if (len
>= 5 && !memcmp( p
, "apos;", 5 ))
1249 ULONG start
, nb_digits
, i
;
1250 int len_utf8
, cp
= 0;
1253 if (!len
) return WS_E_INVALID_FORMAT
;
1259 while (len
&& isxdigit( *p
)) { p
++; len
--; };
1260 if (!len
) return WS_E_INVALID_FORMAT
;
1262 p
-= nb_digits
= start
- len
;
1263 if (!nb_digits
|| nb_digits
> 6 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1264 for (i
= 0; i
< nb_digits
; i
++)
1267 if (*p
>= '0' && *p
<= '9') cp
+= *p
- '0';
1268 else if (*p
>= 'a' && *p
<= 'f') cp
+= *p
- 'a' + 10;
1269 else cp
+= *p
- 'A' + 10;
1273 else if (isdigit( *p
))
1275 while (len
&& *p
== '0') { p
++; len
--; };
1276 if (!len
) return WS_E_INVALID_FORMAT
;
1279 while (len
&& isdigit( *p
)) { p
++; len
--; };
1280 if (!len
) return WS_E_INVALID_FORMAT
;
1282 p
-= nb_digits
= start
- len
;
1283 if (!nb_digits
|| nb_digits
> 7 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1284 for (i
= 0; i
< nb_digits
; i
++)
1291 else return WS_E_INVALID_FORMAT
;
1293 if ((len_utf8
= codepoint_to_utf8( cp
, q
)) < 0) return WS_E_INVALID_FORMAT
;
1294 *ret_len
+= len_utf8
;
1298 else return WS_E_INVALID_FORMAT
;
1310 static HRESULT
read_attribute( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1312 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1313 WS_XML_ATTRIBUTE
*attr
;
1314 WS_XML_UTF8_TEXT
*text
= NULL
;
1315 unsigned int len
= 0, ch
, skip
, quote
;
1316 const unsigned char *start
;
1317 WS_XML_STRING
*prefix
, *localname
;
1318 HRESULT hr
= WS_E_INVALID_FORMAT
;
1320 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1322 start
= read_current_ptr( reader
);
1325 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1326 if (!read_isnamechar( ch
)) break;
1327 read_skip( reader
, skip
);
1330 if (!len
) goto error
;
1332 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1334 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1336 heap_free( prefix
);
1338 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1340 heap_free( localname
);
1343 attr
->localName
= localname
;
1345 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1348 attr
->prefix
= prefix
;
1349 attr
->localName
= localname
;
1353 attr
->prefix
= prefix
;
1354 attr
->localName
= localname
;
1357 hr
= WS_E_INVALID_FORMAT
;
1358 read_skip_whitespace( reader
);
1359 if (read_cmp( reader
, "=", 1 )) goto error
;
1360 read_skip( reader
, 1 );
1362 read_skip_whitespace( reader
);
1363 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) goto error
;
1364 quote
= read_utf8_char( reader
, &skip
);
1365 read_skip( reader
, 1 );
1368 start
= read_current_ptr( reader
);
1371 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1372 if (ch
== quote
) break;
1373 read_skip( reader
, skip
);
1376 read_skip( reader
, 1 );
1381 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1382 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1383 if (!(text
= alloc_utf8_text( NULL
, 0 ))) goto error
;
1387 if (!(text
= alloc_utf8_text( NULL
, len
))) goto error
;
1388 if ((hr
= decode_text( start
, len
, text
->value
.bytes
, &text
->value
.length
)) != S_OK
) goto error
;
1391 attr
->value
= &text
->text
;
1392 attr
->singleQuote
= (quote
== '\'');
1399 free_attribute( attr
);
1403 static inline BOOL
is_valid_parent( const struct node
*node
)
1405 if (!node
) return FALSE
;
1406 return node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
|| node_type( node
) == WS_XML_NODE_TYPE_BOF
;
1409 struct node
*find_parent( struct node
*node
)
1411 if (is_valid_parent( node
)) return node
;
1412 if (is_valid_parent( node
->parent
)) return node
->parent
;
1416 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1418 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1419 const WS_XML_STRING
*ns
;
1422 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1423 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1424 if (!elem
->ns
->length
) elem
->ns
->bytes
= (BYTE
*)(elem
->ns
+ 1); /* quirk */
1426 for (i
= 0; i
< elem
->attributeCount
; i
++)
1428 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1429 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1430 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1431 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1436 static HRESULT
read_element( struct reader
*reader
)
1438 unsigned int len
= 0, ch
, skip
;
1439 const unsigned char *start
;
1440 struct node
*node
= NULL
, *endnode
, *parent
;
1441 WS_XML_ELEMENT_NODE
*elem
;
1442 WS_XML_ATTRIBUTE
*attr
= NULL
;
1443 HRESULT hr
= WS_E_INVALID_FORMAT
;
1445 if (read_end_of_data( reader
))
1447 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1448 reader
->last
= reader
->current
;
1449 reader
->state
= READER_STATE_EOF
;
1453 if (read_cmp( reader
, "<", 1 )) goto error
;
1454 read_skip( reader
, 1 );
1455 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1457 read_rewind( reader
, 1 );
1461 start
= read_current_ptr( reader
);
1464 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1465 if (!read_isnamechar( ch
)) break;
1466 read_skip( reader
, skip
);
1469 if (!len
) goto error
;
1471 if (!(parent
= find_parent( reader
->current
))) goto error
;
1474 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) goto error
;
1475 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) goto error
;
1476 list_add_tail( &node
->children
, &endnode
->entry
);
1477 endnode
->parent
= node
;
1479 elem
= (WS_XML_ELEMENT_NODE
*)node
;
1480 if ((hr
= parse_name( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1482 reader
->current_attr
= 0;
1485 read_skip_whitespace( reader
);
1486 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1487 if ((hr
= read_attribute( reader
, &attr
)) != S_OK
) goto error
;
1488 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1490 free_attribute( attr
);
1493 reader
->current_attr
++;
1495 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1497 read_insert_node( reader
, parent
, node
);
1498 reader
->state
= READER_STATE_STARTELEMENT
;
1502 destroy_nodes( node
);
1506 static HRESULT
read_text( struct reader
*reader
)
1508 unsigned int len
= 0, ch
, skip
;
1509 const unsigned char *start
;
1510 struct node
*node
, *parent
;
1511 WS_XML_TEXT_NODE
*text
;
1512 WS_XML_UTF8_TEXT
*utf8
;
1515 start
= read_current_ptr( reader
);
1518 if (read_end_of_data( reader
)) break;
1519 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1520 if (ch
== '<') break;
1521 read_skip( reader
, skip
);
1525 if (!(parent
= find_parent( reader
->current
))) return WS_E_INVALID_FORMAT
;
1527 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1528 text
= (WS_XML_TEXT_NODE
*)node
;
1529 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
1532 return E_OUTOFMEMORY
;
1534 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1540 text
->text
= &utf8
->text
;
1542 read_insert_node( reader
, parent
, node
);
1543 reader
->state
= READER_STATE_TEXT
;
1547 static HRESULT
read_node( struct reader
* );
1549 static HRESULT
read_startelement( struct reader
*reader
)
1551 read_skip_whitespace( reader
);
1552 if (!read_cmp( reader
, "/>", 2 ))
1554 read_skip( reader
, 2 );
1555 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->children
), struct node
, entry
);
1556 reader
->last
= reader
->current
;
1557 reader
->state
= READER_STATE_ENDELEMENT
;
1560 else if (!read_cmp( reader
, ">", 1 ))
1562 read_skip( reader
, 1 );
1563 return read_node( reader
);
1565 return WS_E_INVALID_FORMAT
;
1568 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
1572 switch (reader
->state
)
1574 case READER_STATE_INITIAL
:
1575 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
1578 case READER_STATE_STARTELEMENT
:
1579 if (found
) *found
= TRUE
;
1586 read_skip_whitespace( reader
);
1587 if ((hr
= read_element( reader
)) == S_OK
&& found
)
1589 if (reader
->state
== READER_STATE_STARTELEMENT
)
1598 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
1601 if (len1
!= len2
) return 1;
1602 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
1606 static struct node
*read_find_startelement( struct reader
*reader
, const WS_XML_STRING
*prefix
,
1607 const WS_XML_STRING
*localname
)
1609 struct node
*parent
;
1610 const WS_XML_STRING
*str
;
1612 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
1614 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1616 str
= parent
->hdr
.prefix
;
1617 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
1618 str
= parent
->hdr
.localName
;
1619 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
1626 static HRESULT
read_endelement( struct reader
*reader
)
1628 struct node
*parent
;
1629 unsigned int len
= 0, ch
, skip
;
1630 const unsigned char *start
;
1631 WS_XML_STRING
*prefix
, *localname
;
1634 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
1636 if (read_end_of_data( reader
))
1638 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1639 reader
->last
= reader
->current
;
1640 reader
->state
= READER_STATE_EOF
;
1644 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
1645 read_skip( reader
, 2 );
1647 start
= read_current_ptr( reader
);
1650 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1653 read_skip( reader
, 1 );
1656 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
1657 read_skip( reader
, skip
);
1661 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
1662 parent
= read_find_startelement( reader
, prefix
, localname
);
1663 heap_free( prefix
);
1664 heap_free( localname
);
1665 if (!parent
) return WS_E_INVALID_FORMAT
;
1667 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
1668 reader
->last
= reader
->current
;
1669 reader
->state
= READER_STATE_ENDELEMENT
;
1673 static HRESULT
read_comment( struct reader
*reader
)
1675 unsigned int len
= 0, ch
, skip
;
1676 const unsigned char *start
;
1677 struct node
*node
, *parent
;
1678 WS_XML_COMMENT_NODE
*comment
;
1680 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
1681 read_skip( reader
, 4 );
1683 start
= read_current_ptr( reader
);
1686 if (!read_cmp( reader
, "-->", 3 ))
1688 read_skip( reader
, 3 );
1691 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1692 read_skip( reader
, skip
);
1696 if (!(parent
= find_parent( reader
->current
))) return WS_E_INVALID_FORMAT
;
1698 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
1699 comment
= (WS_XML_COMMENT_NODE
*)node
;
1700 if (!(comment
->value
.bytes
= heap_alloc( len
)))
1703 return E_OUTOFMEMORY
;
1705 memcpy( comment
->value
.bytes
, start
, len
);
1706 comment
->value
.length
= len
;
1708 read_insert_node( reader
, parent
, node
);
1709 reader
->state
= READER_STATE_COMMENT
;
1713 static HRESULT
read_startcdata( struct reader
*reader
)
1715 struct node
*node
, *endnode
, *parent
;
1717 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
1718 read_skip( reader
, 9 );
1720 if (!(parent
= find_parent( reader
->current
))) return WS_E_INVALID_FORMAT
;
1722 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1723 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
)))
1726 return E_OUTOFMEMORY
;
1728 list_add_tail( &node
->children
, &endnode
->entry
);
1729 endnode
->parent
= node
;
1731 read_insert_node( reader
, parent
, node
);
1732 reader
->state
= READER_STATE_STARTCDATA
;
1736 static HRESULT
read_cdata( struct reader
*reader
)
1738 unsigned int len
= 0, ch
, skip
;
1739 const unsigned char *start
;
1741 WS_XML_TEXT_NODE
*text
;
1742 WS_XML_UTF8_TEXT
*utf8
;
1744 start
= read_current_ptr( reader
);
1747 if (!read_cmp( reader
, "]]>", 3 )) break;
1748 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1749 read_skip( reader
, skip
);
1753 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1754 text
= (WS_XML_TEXT_NODE
*)node
;
1755 if (!(utf8
= alloc_utf8_text( start
, len
)))
1758 return E_OUTOFMEMORY
;
1760 text
->text
= &utf8
->text
;
1762 read_insert_node( reader
, reader
->current
, node
);
1763 reader
->state
= READER_STATE_CDATA
;
1767 static HRESULT
read_endcdata( struct reader
*reader
)
1769 struct node
*parent
;
1771 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
1772 read_skip( reader
, 3 );
1774 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
) parent
= reader
->current
->parent
;
1775 else parent
= reader
->current
;
1777 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
1778 reader
->last
= reader
->current
;
1779 reader
->state
= READER_STATE_ENDCDATA
;
1783 static HRESULT
read_node( struct reader
*reader
)
1789 if (read_end_of_data( reader
))
1791 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1792 reader
->last
= reader
->current
;
1793 reader
->state
= READER_STATE_EOF
;
1796 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
1797 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
1798 else if (!read_cmp( reader
, "<?", 2 ))
1800 hr
= read_xmldecl( reader
);
1801 if (FAILED( hr
)) return hr
;
1803 else if (!read_cmp( reader
, "</", 2 )) return read_endelement( reader
);
1804 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
1805 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment( reader
);
1806 else if (!read_cmp( reader
, "<", 1 )) return read_element( reader
);
1807 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement( reader
);
1808 else return read_text( reader
);
1812 /**************************************************************************
1813 * WsReadEndElement [webservices.@]
1815 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1817 struct reader
*reader
= (struct reader
*)handle
;
1819 TRACE( "%p %p\n", handle
, error
);
1820 if (error
) FIXME( "ignoring error parameter\n" );
1822 if (!reader
) return E_INVALIDARG
;
1823 return read_endelement( reader
);
1826 /**************************************************************************
1827 * WsReadNode [webservices.@]
1829 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
1831 struct reader
*reader
= (struct reader
*)handle
;
1833 TRACE( "%p %p\n", handle
, error
);
1834 if (error
) FIXME( "ignoring error parameter\n" );
1836 if (!reader
) return E_INVALIDARG
;
1837 return read_node( reader
);
1840 /**************************************************************************
1841 * WsReadStartElement [webservices.@]
1843 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1845 struct reader
*reader
= (struct reader
*)handle
;
1847 TRACE( "%p %p\n", handle
, error
);
1848 if (error
) FIXME( "ignoring error parameter\n" );
1850 if (!reader
) return E_INVALIDARG
;
1851 return read_startelement( reader
);
1854 /**************************************************************************
1855 * WsReadToStartElement [webservices.@]
1857 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
1858 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
1860 struct reader
*reader
= (struct reader
*)handle
;
1862 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
1863 if (error
) FIXME( "ignoring error parameter\n" );
1865 if (!reader
) return E_INVALIDARG
;
1866 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
1868 return read_to_startelement( reader
, found
);
1871 BOOL
move_to_root_element( struct node
*root
, struct node
**current
)
1876 if (!(ptr
= list_head( &root
->children
))) return FALSE
;
1877 node
= LIST_ENTRY( ptr
, struct node
, entry
);
1878 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
1883 while ((ptr
= list_next( &root
->children
, &node
->entry
)))
1885 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1886 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1896 BOOL
move_to_next_element( struct node
**current
)
1899 struct node
*node
= *current
, *parent
= (*current
)->parent
;
1901 if (!parent
) return FALSE
;
1902 while ((ptr
= list_next( &parent
->children
, &node
->entry
)))
1904 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1905 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1915 BOOL
move_to_prev_element( struct node
**current
)
1918 struct node
*node
= *current
, *parent
= (*current
)->parent
;
1920 if (!parent
) return FALSE
;
1921 while ((ptr
= list_prev( &parent
->children
, &node
->entry
)))
1923 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
1924 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
1934 BOOL
move_to_child_element( struct node
**current
)
1937 struct node
*child
, *node
= *current
;
1939 if (!(ptr
= list_head( &node
->children
))) return FALSE
;
1940 child
= LIST_ENTRY( ptr
, struct node
, entry
);
1941 if (node_type( child
) == WS_XML_NODE_TYPE_ELEMENT
)
1946 while ((ptr
= list_next( &node
->children
, &child
->entry
)))
1948 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1949 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1959 BOOL
move_to_end_element( struct node
**current
)
1962 struct node
*node
= *current
;
1964 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
1966 if ((ptr
= list_tail( &node
->children
)))
1968 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
1969 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1978 BOOL
move_to_parent_element( struct node
**current
)
1980 struct node
*parent
= (*current
)->parent
;
1982 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
1983 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
1991 BOOL
move_to_first_node( struct node
**current
)
1994 struct node
*node
= *current
;
1996 if ((ptr
= list_head( &node
->parent
->children
)))
1998 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2004 BOOL
move_to_next_node( struct node
**current
)
2007 struct node
*node
= *current
;
2009 if ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
2011 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2017 BOOL
move_to_prev_node( struct node
**current
)
2020 struct node
*node
= *current
;
2022 if ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
2024 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2030 BOOL
move_to_bof( struct node
*root
, struct node
**current
)
2036 BOOL
move_to_eof( struct node
*root
, struct node
**current
)
2039 if ((ptr
= list_tail( &root
->children
)))
2041 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2047 BOOL
move_to_child_node( struct node
**current
)
2050 struct node
*node
= *current
;
2052 if ((ptr
= list_head( &node
->children
)))
2054 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2060 BOOL
move_to_parent_node( struct node
**current
)
2062 struct node
*parent
= (*current
)->parent
;
2063 if (!parent
) return FALSE
;
2068 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
2070 BOOL success
= FALSE
;
2073 if (!read_end_of_data( reader
))
2075 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
2076 if (hr
!= S_OK
) return hr
;
2080 case WS_MOVE_TO_ROOT_ELEMENT
:
2081 success
= move_to_root_element( reader
->root
, &reader
->current
);
2084 case WS_MOVE_TO_NEXT_ELEMENT
:
2085 success
= move_to_next_element( &reader
->current
);
2088 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
2089 success
= move_to_prev_element( &reader
->current
);
2092 case WS_MOVE_TO_CHILD_ELEMENT
:
2093 success
= move_to_child_element( &reader
->current
);
2096 case WS_MOVE_TO_END_ELEMENT
:
2097 success
= move_to_end_element( &reader
->current
);
2100 case WS_MOVE_TO_PARENT_ELEMENT
:
2101 success
= move_to_parent_element( &reader
->current
);
2104 case WS_MOVE_TO_FIRST_NODE
:
2105 success
= move_to_first_node( &reader
->current
);
2108 case WS_MOVE_TO_NEXT_NODE
:
2109 success
= move_to_next_node( &reader
->current
);
2112 case WS_MOVE_TO_PREVIOUS_NODE
:
2113 success
= move_to_prev_node( &reader
->current
);
2116 case WS_MOVE_TO_CHILD_NODE
:
2117 success
= move_to_child_node( &reader
->current
);
2120 case WS_MOVE_TO_BOF
:
2121 success
= move_to_bof( reader
->root
, &reader
->current
);
2124 case WS_MOVE_TO_EOF
:
2125 success
= move_to_eof( reader
->root
, &reader
->current
);
2129 FIXME( "unhandled move %u\n", move
);
2138 return success
? S_OK
: WS_E_INVALID_FORMAT
;
2141 /**************************************************************************
2142 * WsMoveReader [webservices.@]
2144 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
2146 struct reader
*reader
= (struct reader
*)handle
;
2148 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
2149 if (error
) FIXME( "ignoring error parameter\n" );
2151 if (!reader
) return E_INVALIDARG
;
2152 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
2154 return read_move_to( reader
, move
, found
);
2157 /**************************************************************************
2158 * WsReadStartAttribute [webservices.@]
2160 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
2162 struct reader
*reader
= (struct reader
*)handle
;
2163 WS_XML_ELEMENT_NODE
*elem
;
2165 TRACE( "%p %u %p\n", handle
, index
, error
);
2166 if (error
) FIXME( "ignoring error parameter\n" );
2168 if (!reader
) return E_INVALIDARG
;
2170 elem
= &reader
->current
->hdr
;
2171 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
2172 return WS_E_INVALID_FORMAT
;
2174 reader
->current_attr
= index
;
2175 reader
->state
= READER_STATE_STARTATTRIBUTE
;
2179 /**************************************************************************
2180 * WsReadEndAttribute [webservices.@]
2182 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
2184 struct reader
*reader
= (struct reader
*)handle
;
2186 TRACE( "%p %p\n", handle
, error
);
2187 if (error
) FIXME( "ignoring error parameter\n" );
2189 if (!reader
) return E_INVALIDARG
;
2191 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
2192 return WS_E_INVALID_FORMAT
;
2194 reader
->state
= READER_STATE_STARTELEMENT
;
2198 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
2202 switch (text
->textType
)
2204 case WS_XML_TEXT_TYPE_UTF8
:
2206 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2207 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
2208 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
2209 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
2214 FIXME( "unhandled type %u\n", text
->textType
);
2221 #define MAX_INT8 0x7f
2222 #define MIN_INT8 (-MAX_INT8 - 1)
2223 #define MAX_INT16 0x7fff
2224 #define MIN_INT16 (-MAX_INT16 - 1)
2225 #define MAX_INT32 0x7fffffff
2226 #define MIN_INT32 (-MAX_INT32 - 1)
2227 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
2228 #define MIN_INT64 (-MAX_INT64 - 1)
2229 #define MAX_UINT8 0xff
2230 #define MAX_UINT16 0xffff
2231 #define MAX_UINT32 0xffffffff
2232 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
2234 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
2236 BOOL negative
= FALSE
;
2237 const unsigned char *ptr
= str
;
2240 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
2241 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
2242 if (!len
) return WS_E_INVALID_FORMAT
;
2250 if (!len
) return WS_E_INVALID_FORMAT
;
2256 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
2258 if (negative
) val
= -val
;
2260 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
2261 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
2263 return WS_E_NUMERIC_OVERFLOW
;
2265 *ret
= *ret
* 10 + val
;
2272 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
2274 const unsigned char *ptr
= str
;
2277 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
2278 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
2279 if (!len
) return WS_E_INVALID_FORMAT
;
2285 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
2288 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
2289 *ret
= *ret
* 10 + val
;
2296 #if defined(__i386__) || defined(__x86_64__)
2298 #define RC_DOWN 0x100;
2299 BOOL
set_fp_rounding( unsigned short *save
)
2302 unsigned short fpword
;
2304 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
2307 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
2310 FIXME( "not implemented\n" );
2314 void restore_fp_rounding( unsigned short fpword
)
2317 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
2319 FIXME( "not implemented\n" );
2323 BOOL
set_fp_rounding( unsigned short *save
)
2325 FIXME( "not implemented\n" );
2328 void restore_fp_rounding( unsigned short fpword
)
2330 FIXME( "not implemented\n" );
2334 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
2336 static const unsigned __int64 nan
= 0xfff8000000000000;
2337 static const unsigned __int64 inf
= 0x7ff0000000000000;
2338 static const unsigned __int64 inf_min
= 0xfff0000000000000;
2339 HRESULT hr
= WS_E_INVALID_FORMAT
;
2340 const unsigned char *p
= str
, *q
;
2341 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
2342 unsigned __int64 val
= 0, tmp
;
2343 long double exp_val
= 1.0, exp_mul
= 10.0;
2344 unsigned short fpword
;
2346 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2347 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2348 if (!len
) return WS_E_INVALID_FORMAT
;
2350 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
2352 *(unsigned __int64
*)ret
= nan
;
2355 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
2357 *(unsigned __int64
*)ret
= inf
;
2360 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
2362 *(unsigned __int64
*)ret
= inf_min
;
2372 else if (*p
== '+') { p
++; len
--; };
2373 if (!len
) return S_OK
;
2375 if (!set_fp_rounding( &fpword
)) return E_NOTIMPL
;
2378 while (len
&& isdigit( *q
)) { q
++; len
--; }
2379 have_digits
= nb_digits
= q
- p
;
2380 for (i
= 0; i
< nb_digits
; i
++)
2382 tmp
= val
* 10 + p
[i
] - '0';
2383 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
2385 for (; i
< nb_digits
; i
++) exp
++;
2396 while (len
&& isdigit( *q
)) { q
++; len
--; };
2397 have_digits
|= nb_digits
= q
- p
;
2398 for (i
= 0; i
< nb_digits
; i
++)
2400 tmp
= val
* 10 + p
[i
] - '0';
2401 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
2406 if (len
> 1 && tolower(*q
) == 'e')
2408 if (!have_digits
) goto done
;
2415 else if (*p
== '+') { p
++; len
--; };
2418 while (len
&& isdigit( *q
)) { q
++; len
--; };
2420 if (!nb_digits
|| len
) goto done
;
2421 for (i
= 0; i
< nb_digits
; i
++)
2423 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
2424 exp_tmp
= MAX_INT32
;
2426 exp_tmp
*= exp_sign
;
2428 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
2429 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
2430 else exp
+= exp_tmp
;
2433 if (!have_digits
|| len
) goto done
;
2435 if ((neg_exp
= exp
< 0)) exp
= -exp
;
2436 for (; exp
; exp
>>= 1)
2438 if (exp
& 1) exp_val
*= exp_mul
;
2442 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
2446 restore_fp_rounding( fpword
);
2450 static HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
2452 static const unsigned char hex
[] =
2454 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
2455 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
2456 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
2457 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
2458 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
2459 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
2460 0,10,11,12,13,14,15 /* 0x60 */
2462 const unsigned char *p
= str
;
2465 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2466 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2467 if (len
!= 36) return WS_E_INVALID_FORMAT
;
2469 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
2470 return WS_E_INVALID_FORMAT
;
2472 for (i
= 0; i
< 36; i
++)
2474 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
2475 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
2478 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
2479 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
2481 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
2482 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
2484 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
2485 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
2486 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
2487 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
2488 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
2489 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
2490 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
2491 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
2496 static inline unsigned char decode_char( unsigned char c
)
2498 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
2499 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
2500 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
2501 if (c
== '+') return 62;
2502 if (c
== '/') return 63;
2506 static ULONG
decode_base64( const unsigned char *base64
, ULONG len
, unsigned char *buf
)
2509 unsigned char c0
, c1
, c2
, c3
;
2510 const unsigned char *p
= base64
;
2514 if ((c0
= decode_char( p
[0] )) > 63) return 0;
2515 if ((c1
= decode_char( p
[1] )) > 63) return 0;
2516 if ((c2
= decode_char( p
[2] )) > 63) return 0;
2517 if ((c3
= decode_char( p
[3] )) > 63) return 0;
2518 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
2519 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
2520 buf
[i
+ 2] = (c2
<< 6) | c3
;
2527 if ((c0
= decode_char( p
[0] )) > 63) return 0;
2528 if ((c1
= decode_char( p
[1] )) > 63) return 0;
2529 buf
[i
] = (c0
<< 2) | (c1
>> 4);
2532 else if (p
[3] == '=')
2534 if ((c0
= decode_char( p
[0] )) > 63) return 0;
2535 if ((c1
= decode_char( p
[1] )) > 63) return 0;
2536 if ((c2
= decode_char( p
[2] )) > 63) return 0;
2537 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
2538 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
2543 if ((c0
= decode_char( p
[0] )) > 63) return 0;
2544 if ((c1
= decode_char( p
[1] )) > 63) return 0;
2545 if ((c2
= decode_char( p
[2] )) > 63) return 0;
2546 if ((c3
= decode_char( p
[3] )) > 63) return 0;
2547 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
2548 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
2549 buf
[i
+ 2] = (c2
<< 6) | c3
;
2555 static HRESULT
str_to_bytes( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_BYTES
*ret
)
2557 const unsigned char *p
= str
;
2559 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2560 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2562 if (len
% 4) return WS_E_INVALID_FORMAT
;
2563 if (!(ret
->bytes
= ws_alloc( heap
, len
* 3 / 4 ))) return WS_E_QUOTA_EXCEEDED
;
2564 ret
->length
= decode_base64( p
, len
, ret
->bytes
);
2568 static const int month_offsets
[2][12] =
2570 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
2571 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
2574 static inline int valid_day( int year
, int month
, int day
)
2576 return day
> 0 && day
<= month_days
[leap_year( year
)][month
- 1];
2579 static inline int leap_days_before( int year
)
2581 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
2584 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
2586 const unsigned char *p
= bytes
, *q
;
2587 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
2589 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2590 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2593 while (len
&& isdigit( *q
)) { q
++; len
--; };
2594 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2595 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
2596 if (year
< 1) return WS_E_INVALID_FORMAT
;
2599 while (len
&& isdigit( *q
)) { q
++; len
--; };
2600 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2601 month
= (p
[0] - '0') * 10 + p
[1] - '0';
2602 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
2605 while (len
&& isdigit( *q
)) { q
++; len
--; };
2606 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
2607 day
= (p
[0] - '0') * 10 + p
[1] - '0';
2608 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
2611 while (len
&& isdigit( *q
)) { q
++; len
--; };
2612 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2613 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2614 if (hour
> 24) return WS_E_INVALID_FORMAT
;
2617 while (len
&& isdigit( *q
)) { q
++; len
--; };
2618 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2619 min
= (p
[0] - '0') * 10 + p
[1] - '0';
2620 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2623 while (len
&& isdigit( *q
)) { q
++; len
--; };
2624 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
2625 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
2626 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2630 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
2632 while (len
&& isdigit( *q
)) { q
++; len
--; };
2634 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
2635 for (i
= 0; i
< nb_digits
; i
++)
2637 sec_frac
+= (p
[i
] - '0') * mul
;
2643 if (--len
) return WS_E_INVALID_FORMAT
;
2644 tz_hour
= tz_min
= tz_neg
= 0;
2645 ret
->format
= WS_DATETIME_FORMAT_UTC
;
2647 else if (*q
== '+' || *q
== '-')
2649 tz_neg
= (*q
== '-') ? 1 : 0;
2652 while (len
&& isdigit( *q
)) { q
++; len
--; };
2653 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2654 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2655 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
2658 while (len
&& isdigit( *q
)) { q
++; len
--; };
2659 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
2660 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
2661 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
2663 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
2665 else return WS_E_INVALID_FORMAT
;
2667 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
2668 ret
->ticks
+= month_offsets
[leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
2669 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
2670 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
2671 ret
->ticks
+= min
* TICKS_PER_MIN
;
2672 ret
->ticks
+= sec
* TICKS_PER_SEC
;
2673 ret
->ticks
+= sec_frac
;
2677 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
2678 return WS_E_INVALID_FORMAT
;
2679 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
2680 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
2684 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
2685 return WS_E_INVALID_FORMAT
;
2686 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
2687 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
2693 /**************************************************************************
2694 * WsDateTimeToFileTime [webservices.@]
2696 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
2698 unsigned __int64 ticks
;
2700 TRACE( "%p %p %p\n", dt
, ft
, error
);
2701 if (error
) FIXME( "ignoring error parameter\n" );
2703 if (!dt
|| !ft
) return E_INVALIDARG
;
2705 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
2706 ticks
= dt
->ticks
- TICKS_1601_01_01
;
2707 ft
->dwHighDateTime
= ticks
>> 32;
2708 ft
->dwLowDateTime
= (DWORD
)ticks
;
2712 /**************************************************************************
2713 * WsFileTimeToDateTime [webservices.@]
2715 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
2717 unsigned __int64 ticks
;
2719 TRACE( "%p %p %p\n", ft
, dt
, error
);
2720 if (error
) FIXME( "ignoring error parameter\n" );
2722 if (!dt
|| !ft
) return E_INVALIDARG
;
2724 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
2725 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
2726 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
2727 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
2728 dt
->format
= WS_DATETIME_FORMAT_UTC
;
2732 static HRESULT
read_get_node_text( struct reader
*reader
, WS_XML_UTF8_TEXT
**ret
)
2734 WS_XML_TEXT_NODE
*text
;
2736 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
2737 return WS_E_INVALID_FORMAT
;
2739 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
2740 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2742 FIXME( "text type %u not supported\n", text
->text
->textType
);
2745 *ret
= (WS_XML_UTF8_TEXT
*)text
->text
;
2749 static HRESULT
read_get_attribute_text( struct reader
*reader
, ULONG index
, WS_XML_UTF8_TEXT
**ret
)
2751 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2752 WS_XML_ATTRIBUTE
*attr
;
2754 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2755 return WS_E_INVALID_FORMAT
;
2757 attr
= elem
->attributes
[index
];
2758 if (attr
->value
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2760 FIXME( "text type %u not supported\n", attr
->value
->textType
);
2763 *ret
= (WS_XML_UTF8_TEXT
*)attr
->value
;
2767 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
2768 const WS_XML_STRING
*ns
, ULONG
*index
)
2771 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2775 *index
= reader
->current_attr
;
2778 for (i
= 0; i
< elem
->attributeCount
; i
++)
2780 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
2781 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
2783 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
2784 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
2793 /**************************************************************************
2794 * WsFindAttribute [webservices.@]
2796 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2797 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
2800 struct reader
*reader
= (struct reader
*)handle
;
2802 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
2803 required
, index
, error
);
2804 if (error
) FIXME( "ignoring error parameter\n" );
2806 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
2808 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2809 return WS_E_INVALID_OPERATION
;
2811 if (!find_attribute( reader
, localname
, ns
, index
))
2813 if (required
) return WS_E_INVALID_FORMAT
;
2820 static HRESULT
read_get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2821 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2822 WS_XML_UTF8_TEXT
**ret
, BOOL
*found
)
2826 case WS_ATTRIBUTE_TYPE_MAPPING
:
2829 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
2830 return read_get_attribute_text( reader
, index
, ret
);
2832 case WS_ELEMENT_TYPE_MAPPING
:
2833 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2834 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2840 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2842 if (WsXmlStringEquals( localname
, elem
->localName
, NULL
) != S_OK
||
2843 WsXmlStringEquals( ns
, elem
->ns
, NULL
) != S_OK
)
2848 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
2850 return read_get_node_text( reader
, ret
);
2853 FIXME( "mapping %u not supported\n", mapping
);
2858 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2859 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2860 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2861 WS_HEAP
*heap
, void *ret
, ULONG size
)
2863 WS_XML_UTF8_TEXT
*utf8
;
2865 BOOL found
, val
= FALSE
;
2869 FIXME( "description not supported\n" );
2872 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2875 ULONG len
= utf8
->value
.length
;
2876 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
2877 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
2878 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
2879 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
2880 else return WS_E_INVALID_FORMAT
;
2885 case WS_READ_REQUIRED_VALUE
:
2886 if (!found
) return WS_E_INVALID_FORMAT
;
2889 case WS_READ_NILLABLE_VALUE
:
2890 if (size
!= sizeof(BOOL
)) return E_INVALIDARG
;
2894 case WS_READ_REQUIRED_POINTER
:
2895 if (!found
) return WS_E_INVALID_FORMAT
;
2898 case WS_READ_OPTIONAL_POINTER
:
2899 case WS_READ_NILLABLE_POINTER
:
2901 BOOL
*heap_val
= NULL
;
2902 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2905 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2908 *(BOOL
**)ret
= heap_val
;
2912 FIXME( "read option %u not supported\n", option
);
2919 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2920 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2921 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2922 WS_HEAP
*heap
, void *ret
, ULONG size
)
2924 WS_XML_UTF8_TEXT
*utf8
;
2931 FIXME( "description not supported\n" );
2934 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2935 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
2940 case WS_READ_REQUIRED_VALUE
:
2941 if (!found
) return WS_E_INVALID_FORMAT
;
2944 case WS_READ_NILLABLE_VALUE
:
2945 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
2949 case WS_READ_REQUIRED_POINTER
:
2950 if (!found
) return WS_E_INVALID_FORMAT
;
2953 case WS_READ_OPTIONAL_POINTER
:
2954 case WS_READ_NILLABLE_POINTER
:
2956 INT8
*heap_val
= NULL
;
2957 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2960 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2963 *(INT8
**)ret
= heap_val
;
2967 FIXME( "read option %u not supported\n", option
);
2974 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2975 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2976 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2977 WS_HEAP
*heap
, void *ret
, ULONG size
)
2979 WS_XML_UTF8_TEXT
*utf8
;
2986 FIXME( "description not supported\n" );
2989 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2990 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
2995 case WS_READ_REQUIRED_VALUE
:
2996 if (!found
) return WS_E_INVALID_FORMAT
;
2999 case WS_READ_NILLABLE_VALUE
:
3000 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
3001 *(INT16
*)ret
= val
;
3004 case WS_READ_REQUIRED_POINTER
:
3005 if (!found
) return WS_E_INVALID_FORMAT
;
3008 case WS_READ_OPTIONAL_POINTER
:
3009 case WS_READ_NILLABLE_POINTER
:
3011 INT16
*heap_val
= NULL
;
3012 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3015 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3018 *(INT16
**)ret
= heap_val
;
3022 FIXME( "read option %u not supported\n", option
);
3029 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3030 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3031 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3032 WS_HEAP
*heap
, void *ret
, ULONG size
)
3034 WS_XML_UTF8_TEXT
*utf8
;
3041 FIXME( "description not supported\n" );
3044 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3045 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
3050 case WS_READ_REQUIRED_VALUE
:
3051 if (!found
) return WS_E_INVALID_FORMAT
;
3054 case WS_READ_NILLABLE_VALUE
:
3055 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
3056 *(INT32
*)ret
= val
;
3059 case WS_READ_REQUIRED_POINTER
:
3060 if (!found
) return WS_E_INVALID_FORMAT
;
3063 case WS_READ_OPTIONAL_POINTER
:
3064 case WS_READ_NILLABLE_POINTER
:
3066 INT32
*heap_val
= NULL
;
3067 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3070 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3073 *(INT32
**)ret
= heap_val
;
3077 FIXME( "read option %u not supported\n", option
);
3084 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3085 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3086 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3087 WS_HEAP
*heap
, void *ret
, ULONG size
)
3089 WS_XML_UTF8_TEXT
*utf8
;
3096 FIXME( "description not supported\n" );
3099 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3100 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
3105 case WS_READ_REQUIRED_VALUE
:
3106 if (!found
) return WS_E_INVALID_FORMAT
;
3109 case WS_READ_NILLABLE_VALUE
:
3110 if (size
!= sizeof(INT64
)) return E_INVALIDARG
;
3111 *(INT64
*)ret
= val
;
3114 case WS_READ_REQUIRED_POINTER
:
3115 if (!found
) return WS_E_INVALID_FORMAT
;
3118 case WS_READ_OPTIONAL_POINTER
:
3119 case WS_READ_NILLABLE_POINTER
:
3121 INT64
*heap_val
= NULL
;
3122 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3125 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3128 *(INT64
**)ret
= heap_val
;
3132 FIXME( "read option %u not supported\n", option
);
3139 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3140 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3141 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3142 WS_HEAP
*heap
, void *ret
, ULONG size
)
3144 WS_XML_UTF8_TEXT
*utf8
;
3151 FIXME( "description not supported\n" );
3154 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3155 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
3160 case WS_READ_REQUIRED_VALUE
:
3161 if (!found
) return WS_E_INVALID_FORMAT
;
3164 case WS_READ_NILLABLE_VALUE
:
3165 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
3166 *(UINT8
*)ret
= val
;
3169 case WS_READ_REQUIRED_POINTER
:
3170 if (!found
) return WS_E_INVALID_FORMAT
;
3173 case WS_READ_OPTIONAL_POINTER
:
3174 case WS_READ_NILLABLE_POINTER
:
3176 UINT8
*heap_val
= NULL
;
3177 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3180 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3183 *(UINT8
**)ret
= heap_val
;
3187 FIXME( "read option %u not supported\n", option
);
3194 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3195 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3196 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3197 WS_HEAP
*heap
, void *ret
, ULONG size
)
3199 WS_XML_UTF8_TEXT
*utf8
;
3206 FIXME( "description not supported\n" );
3209 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3210 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
3215 case WS_READ_REQUIRED_VALUE
:
3216 if (!found
) return WS_E_INVALID_FORMAT
;
3219 case WS_READ_NILLABLE_VALUE
:
3220 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
3221 *(UINT16
*)ret
= val
;
3224 case WS_READ_REQUIRED_POINTER
:
3225 if (!found
) return WS_E_INVALID_FORMAT
;
3228 case WS_READ_OPTIONAL_POINTER
:
3229 case WS_READ_NILLABLE_POINTER
:
3231 UINT16
*heap_val
= NULL
;
3232 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3235 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3238 *(UINT16
**)ret
= heap_val
;
3242 FIXME( "read option %u not supported\n", option
);
3249 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3250 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3251 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3252 WS_HEAP
*heap
, void *ret
, ULONG size
)
3254 WS_XML_UTF8_TEXT
*utf8
;
3261 FIXME( "description not supported\n" );
3264 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3265 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
3270 case WS_READ_REQUIRED_VALUE
:
3271 if (!found
) return WS_E_INVALID_FORMAT
;
3274 case WS_READ_NILLABLE_VALUE
:
3275 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
3276 *(UINT32
*)ret
= val
;
3279 case WS_READ_REQUIRED_POINTER
:
3280 if (!found
) return WS_E_INVALID_FORMAT
;
3283 case WS_READ_OPTIONAL_POINTER
:
3284 case WS_READ_NILLABLE_POINTER
:
3286 UINT32
*heap_val
= NULL
;
3287 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3290 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3293 *(UINT32
**)ret
= heap_val
;
3297 FIXME( "read option %u not supported\n", option
);
3304 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3305 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3306 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3307 WS_HEAP
*heap
, void *ret
, ULONG size
)
3309 WS_XML_UTF8_TEXT
*utf8
;
3316 FIXME( "description not supported\n" );
3319 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3320 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
)) != S_OK
)
3325 case WS_READ_REQUIRED_VALUE
:
3326 if (!found
) return WS_E_INVALID_FORMAT
;
3329 case WS_READ_NILLABLE_VALUE
:
3330 if (size
!= sizeof(UINT64
)) return E_INVALIDARG
;
3331 *(UINT64
*)ret
= val
;
3334 case WS_READ_REQUIRED_POINTER
:
3335 if (!found
) return WS_E_INVALID_FORMAT
;
3338 case WS_READ_OPTIONAL_POINTER
:
3339 case WS_READ_NILLABLE_POINTER
:
3341 UINT64
*heap_val
= NULL
;
3342 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3345 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3348 *(UINT64
**)ret
= heap_val
;
3352 FIXME( "read option %u not supported\n", option
);
3359 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3360 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3361 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3362 WS_HEAP
*heap
, void *ret
, ULONG size
)
3364 WS_XML_UTF8_TEXT
*utf8
;
3369 if (desc
) FIXME( "ignoring description\n" );
3371 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3372 if (found
&& (hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3376 case WS_READ_REQUIRED_VALUE
:
3377 if (!found
) return WS_E_INVALID_FORMAT
;
3380 case WS_READ_NILLABLE_VALUE
:
3381 if (size
!= sizeof(double)) return E_INVALIDARG
;
3382 *(double *)ret
= val
;
3385 case WS_READ_REQUIRED_POINTER
:
3386 if (!found
) return WS_E_INVALID_FORMAT
;
3389 case WS_READ_OPTIONAL_POINTER
:
3390 case WS_READ_NILLABLE_POINTER
:
3392 double *heap_val
= NULL
;
3393 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3396 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3399 *(double **)ret
= heap_val
;
3403 FIXME( "read option %u not supported\n", option
);
3410 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3411 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3412 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3413 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
3415 WS_XML_UTF8_TEXT
*utf8
;
3422 FIXME( "description not supported\n" );
3425 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3426 if (found
&& !(str
= xmltext_to_widechar( heap
, &utf8
->text
))) return WS_E_QUOTA_EXCEEDED
;
3430 case WS_READ_REQUIRED_POINTER
:
3431 if (!found
) return WS_E_INVALID_FORMAT
;
3434 case WS_READ_OPTIONAL_POINTER
:
3435 case WS_READ_NILLABLE_POINTER
:
3436 if (size
!= sizeof(str
)) return E_INVALIDARG
;
3441 FIXME( "read option %u not supported\n", option
);
3448 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
3451 for (i
= 0; i
< desc
->valueCount
; i
++)
3453 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
3455 *ret
= desc
->values
[i
].value
;
3459 return WS_E_INVALID_FORMAT
;
3462 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3463 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3464 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3465 WS_HEAP
*heap
, void *ret
, ULONG size
)
3467 WS_XML_UTF8_TEXT
*utf8
;
3472 if (!desc
) return E_INVALIDARG
;
3474 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3475 if (found
&& (hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
3479 case WS_READ_REQUIRED_VALUE
:
3480 if (!found
) return WS_E_INVALID_FORMAT
;
3483 case WS_READ_NILLABLE_VALUE
:
3484 if (size
!= sizeof(int)) return E_INVALIDARG
;
3488 case WS_READ_REQUIRED_POINTER
:
3489 if (!found
) return WS_E_INVALID_FORMAT
;
3492 case WS_READ_OPTIONAL_POINTER
:
3493 case WS_READ_NILLABLE_POINTER
:
3495 int *heap_val
= NULL
;
3496 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3499 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3502 *(int **)ret
= heap_val
;
3506 FIXME( "read option %u not supported\n", option
);
3513 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3514 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3515 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3516 WS_HEAP
*heap
, void *ret
, ULONG size
)
3518 WS_XML_UTF8_TEXT
*utf8
;
3520 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
3523 if (desc
) FIXME( "ignoring description\n" );
3525 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3526 if (found
&& (hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3530 case WS_READ_REQUIRED_VALUE
:
3531 if (!found
) return WS_E_INVALID_FORMAT
;
3534 case WS_READ_NILLABLE_VALUE
:
3535 if (size
!= sizeof(WS_DATETIME
)) return E_INVALIDARG
;
3536 *(WS_DATETIME
*)ret
= val
;
3539 case WS_READ_REQUIRED_POINTER
:
3540 if (!found
) return WS_E_INVALID_FORMAT
;
3543 case WS_READ_OPTIONAL_POINTER
:
3544 case WS_READ_NILLABLE_POINTER
:
3546 WS_DATETIME
*heap_val
= NULL
;
3547 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3550 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3553 *(WS_DATETIME
**)ret
= heap_val
;
3557 FIXME( "read option %u not supported\n", option
);
3564 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3565 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3566 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3567 WS_HEAP
*heap
, void *ret
, ULONG size
)
3569 WS_XML_UTF8_TEXT
*utf8
;
3574 if (desc
) FIXME( "ignoring description\n" );
3576 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3577 if (found
&& (hr
= str_to_guid( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3581 case WS_READ_REQUIRED_VALUE
:
3582 if (!found
) return WS_E_INVALID_FORMAT
;
3585 case WS_READ_NILLABLE_VALUE
:
3586 if (size
!= sizeof(GUID
)) return E_INVALIDARG
;
3590 case WS_READ_REQUIRED_POINTER
:
3591 if (!found
) return WS_E_INVALID_FORMAT
;
3594 case WS_READ_OPTIONAL_POINTER
:
3595 case WS_READ_NILLABLE_POINTER
:
3597 GUID
*heap_val
= NULL
;
3598 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3601 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3604 *(GUID
**)ret
= heap_val
;
3608 FIXME( "read option %u not supported\n", option
);
3615 static HRESULT
read_type_bytes( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3616 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3617 const WS_BYTES_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3618 WS_HEAP
*heap
, void *ret
, ULONG size
)
3620 WS_XML_UTF8_TEXT
*utf8
;
3625 if (desc
) FIXME( "ignoring description\n" );
3627 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3628 if (found
&& (hr
= str_to_bytes( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
3633 case WS_READ_REQUIRED_VALUE
:
3634 if (!found
) return WS_E_INVALID_FORMAT
;
3637 case WS_READ_NILLABLE_VALUE
:
3638 if (size
!= sizeof(WS_BYTES
)) return E_INVALIDARG
;
3639 *(WS_BYTES
*)ret
= val
;
3642 case WS_READ_REQUIRED_POINTER
:
3643 if (!found
) return WS_E_INVALID_FORMAT
;
3646 case WS_READ_OPTIONAL_POINTER
:
3647 case WS_READ_NILLABLE_POINTER
:
3649 WS_BYTES
*heap_val
= NULL
;
3650 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3653 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3656 *(WS_BYTES
**)ret
= heap_val
;
3660 FIXME( "read option %u not supported\n", option
);
3667 static BOOL
is_empty_text_node( const struct node
*node
)
3669 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
3670 const WS_XML_UTF8_TEXT
*utf8
;
3673 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
3674 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3676 ERR( "unhandled text type %u\n", text
->text
->textType
);
3679 utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
3680 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
3684 static HRESULT
read_next_node( struct reader
*reader
)
3686 if (reader
->current
== reader
->last
) return read_node( reader
);
3687 if (move_to_child_node( &reader
->current
)) return S_OK
;
3688 if (move_to_next_node( &reader
->current
)) return S_OK
;
3689 if (!move_to_parent_node( &reader
->current
)) return WS_E_INVALID_FORMAT
;
3690 if (move_to_next_node( &reader
->current
)) return S_OK
;
3691 return WS_E_INVALID_FORMAT
;
3694 /* skips comment and empty text nodes */
3695 static HRESULT
read_type_next_node( struct reader
*reader
)
3700 WS_XML_NODE_TYPE type
;
3702 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3703 type
= node_type( reader
->current
);
3704 if (type
== WS_XML_NODE_TYPE_COMMENT
||
3705 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
3710 static BOOL
match_current_element( struct reader
*reader
, const WS_XML_STRING
*localname
,
3711 const WS_XML_STRING
*ns
)
3713 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3714 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
3715 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
3716 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
3719 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
3720 const WS_XML_STRING
*ns
)
3726 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
3727 if (reader
->current
== reader
->last
)
3730 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
3731 if (!found
) return WS_E_INVALID_FORMAT
;
3733 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3735 node
= reader
->current
;
3736 attr
= reader
->current_attr
;
3738 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
3739 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3741 reader
->current
= node
;
3742 reader
->current_attr
= attr
;
3744 return WS_E_INVALID_FORMAT
;
3747 ULONG
get_type_size( WS_TYPE type
, const WS_STRUCT_DESCRIPTION
*desc
)
3753 return sizeof(INT8
);
3756 case WS_UINT16_TYPE
:
3757 return sizeof(INT16
);
3761 case WS_UINT32_TYPE
:
3763 return sizeof(INT32
);
3766 case WS_UINT64_TYPE
:
3767 return sizeof(INT64
);
3769 case WS_DOUBLE_TYPE
:
3770 return sizeof(double);
3772 case WS_DATETIME_TYPE
:
3773 return sizeof(WS_DATETIME
);
3776 return sizeof(GUID
);
3779 return sizeof(WCHAR
*);
3782 return sizeof(WS_BYTES
);
3784 case WS_STRUCT_TYPE
:
3788 ERR( "unhandled type %u\n", type
);
3793 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
, ULONG options
)
3795 if (options
& WS_FIELD_POINTER
)
3797 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
3798 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
3799 return WS_READ_REQUIRED_POINTER
;
3810 case WS_UINT16_TYPE
:
3811 case WS_UINT32_TYPE
:
3812 case WS_UINT64_TYPE
:
3813 case WS_DOUBLE_TYPE
:
3814 case WS_DATETIME_TYPE
:
3817 case WS_STRUCT_TYPE
:
3819 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_READ_NILLABLE_VALUE
;
3820 return WS_READ_REQUIRED_VALUE
;
3823 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
3824 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
3825 return WS_READ_REQUIRED_POINTER
;
3828 FIXME( "unhandled type %u\n", type
);
3833 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
3834 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
3837 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3838 WS_HEAP
*heap
, void **ret
, ULONG
*count
)
3841 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
3842 WS_READ_OPTION option
;
3845 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3847 /* wrapper element */
3848 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
3851 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
3852 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
3854 item_size
= sizeof(void *);
3856 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
3859 if (nb_items
>= nb_allocated
)
3861 if (!(buf
= ws_realloc_zero( heap
, buf
, nb_allocated
* 2 * item_size
)))
3862 return WS_E_QUOTA_EXCEEDED
;
3865 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
3866 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
3867 if (hr
== WS_E_INVALID_FORMAT
) break;
3870 ws_free( heap
, buf
);
3873 offset
+= item_size
;
3877 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
3879 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
3881 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
3882 desc
->itemRange
->maxItemCount
);
3883 ws_free( heap
, buf
);
3884 return WS_E_INVALID_FORMAT
;
3893 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3894 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
3897 if (reader
->current
== reader
->last
)
3900 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
3901 if (!found
) return WS_E_INVALID_FORMAT
;
3903 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3904 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
3906 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
3907 desc
->typeDescription
, option
, heap
, ret
, size
);
3910 static HRESULT
read_type_struct_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3911 WS_HEAP
*heap
, char *buf
)
3914 WS_READ_OPTION option
;
3918 if (!desc
) return E_INVALIDARG
;
3919 if (desc
->options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
3921 FIXME( "options %08x not supported\n", desc
->options
);
3924 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3926 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
3927 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3929 size
= sizeof(void *);
3931 ptr
= buf
+ desc
->offset
;
3932 switch (desc
->mapping
)
3934 case WS_ATTRIBUTE_FIELD_MAPPING
:
3935 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
3936 desc
->typeDescription
, option
, heap
, ptr
, size
);
3939 case WS_ELEMENT_FIELD_MAPPING
:
3940 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
3941 desc
->typeDescription
, option
, heap
, ptr
, size
);
3944 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3947 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, &count
);
3948 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
3951 case WS_TEXT_FIELD_MAPPING
:
3952 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
3956 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
3960 if (hr
== WS_E_INVALID_FORMAT
)
3964 case WS_READ_REQUIRED_VALUE
:
3965 case WS_READ_REQUIRED_POINTER
:
3966 return WS_E_INVALID_FORMAT
;
3968 case WS_READ_NILLABLE_VALUE
:
3969 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
3972 case WS_READ_OPTIONAL_POINTER
:
3973 case WS_READ_NILLABLE_POINTER
:
3974 *(void **)ptr
= NULL
;
3978 ERR( "unhandled option %u\n", option
);
3986 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3987 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3988 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3989 WS_HEAP
*heap
, void *ret
, ULONG size
)
3995 if (!desc
) return E_INVALIDARG
;
3996 if (desc
->structOptions
) FIXME( "struct options %08x not supported\n", desc
->structOptions
);
4000 case WS_READ_REQUIRED_POINTER
:
4001 case WS_READ_OPTIONAL_POINTER
:
4002 case WS_READ_NILLABLE_POINTER
:
4003 if (size
!= sizeof(void *)) return E_INVALIDARG
;
4004 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
4007 case WS_READ_REQUIRED_VALUE
:
4008 case WS_READ_NILLABLE_VALUE
:
4009 if (size
!= desc
->size
) return E_INVALIDARG
;
4014 FIXME( "unhandled read option %u\n", option
);
4018 for (i
= 0; i
< desc
->fieldCount
; i
++)
4020 if ((hr
= read_type_struct_field( reader
, desc
->fields
[i
], heap
, buf
)) != S_OK
)
4026 case WS_READ_REQUIRED_POINTER
:
4029 ws_free( heap
, buf
);
4032 *(char **)ret
= buf
;
4035 case WS_READ_OPTIONAL_POINTER
:
4036 case WS_READ_NILLABLE_POINTER
:
4037 if (is_nil_value( buf
, desc
->size
))
4039 ws_free( heap
, buf
);
4042 *(char **)ret
= buf
;
4045 case WS_READ_REQUIRED_VALUE
:
4046 case WS_READ_NILLABLE_VALUE
:
4050 ERR( "unhandled read option %u\n", option
);
4055 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
4056 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4057 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
,
4058 void *value
, ULONG size
)
4064 case WS_ELEMENT_TYPE_MAPPING
:
4065 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
4066 if ((hr
= read_type_next_element_node( reader
, localname
, ns
)) != S_OK
) return hr
;
4069 case WS_ANY_ELEMENT_TYPE_MAPPING
:
4070 case WS_ATTRIBUTE_TYPE_MAPPING
:
4074 FIXME( "unhandled mapping %u\n", mapping
);
4081 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4086 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4091 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4096 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4101 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4106 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4110 case WS_UINT16_TYPE
:
4111 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4115 case WS_UINT32_TYPE
:
4116 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4120 case WS_UINT64_TYPE
:
4121 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4125 case WS_DOUBLE_TYPE
:
4126 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4130 case WS_DATETIME_TYPE
:
4131 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4136 if ((hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4141 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4146 if ((hr
= read_type_bytes( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4150 case WS_STRUCT_TYPE
:
4151 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4156 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4161 FIXME( "type %u not supported\n", type
);
4167 case WS_ELEMENT_TYPE_MAPPING
:
4168 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
4169 return read_type_next_node( reader
);
4171 case WS_ATTRIBUTE_TYPE_MAPPING
:
4177 /**************************************************************************
4178 * WsReadType [webservices.@]
4180 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
4181 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
4182 ULONG size
, WS_ERROR
*error
)
4184 struct reader
*reader
= (struct reader
*)handle
;
4187 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
4189 if (error
) FIXME( "ignoring error parameter\n" );
4191 if (!reader
|| !value
) return E_INVALIDARG
;
4193 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
4198 case WS_ELEMENT_TYPE_MAPPING
:
4199 if ((hr
= read_node( reader
)) != S_OK
) return hr
;
4206 if (!read_end_of_data( reader
)) return WS_E_INVALID_FORMAT
;
4210 /**************************************************************************
4211 * WsReadElement [webservices.@]
4213 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4214 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
4217 struct reader
*reader
= (struct reader
*)handle
;
4219 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
4220 if (error
) FIXME( "ignoring error parameter\n" );
4222 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
4224 return read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
4225 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
4228 /**************************************************************************
4229 * WsReadValue [webservices.@]
4231 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
4234 struct reader
*reader
= (struct reader
*)handle
;
4235 WS_TYPE type
= map_value_type( value_type
);
4237 TRACE( "%p %u %p %u %p\n", handle
, type
, value
, size
, error
);
4238 if (error
) FIXME( "ignoring error parameter\n" );
4240 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
4242 return read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
4243 NULL
, value
, size
);
4246 /**************************************************************************
4247 * WsSetErrorProperty [webservices.@]
4249 HRESULT WINAPI
WsSetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, const void *value
,
4252 struct error
*error
= (struct error
*)handle
;
4254 TRACE( "%p %u %p %u\n", handle
, id
, value
, size
);
4256 if (id
== WS_ERROR_PROPERTY_LANGID
) return WS_E_INVALID_OPERATION
;
4257 return prop_set( error
->prop
, error
->prop_count
, id
, value
, size
);
4260 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
4262 static const char bom
[] = {0xef,0xbb,0xbf};
4263 const unsigned char *p
= data
;
4265 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
4266 (size
> 2 && !(*offset
= 0));
4269 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
4271 static const char bom
[] = {0xff,0xfe};
4272 const unsigned char *p
= data
;
4274 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
4275 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
4278 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
4282 /* FIXME: parse xml declaration */
4284 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
4285 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
4288 FIXME( "charset not recognized\n" );
4292 TRACE( "detected charset %u\n", ret
);
4296 static void set_input_buffer( struct reader
*reader
, struct xmlbuf
*buf
, const unsigned char *data
, ULONG size
)
4298 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
4299 reader
->input_buf
= buf
;
4300 reader
->input_data
= data
;
4301 reader
->input_size
= size
;
4303 reader
->read_size
= reader
->input_size
;
4304 reader
->read_pos
= 0;
4305 reader
->read_bufptr
= reader
->input_data
;
4308 /**************************************************************************
4309 * WsSetInput [webservices.@]
4311 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
4312 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
4313 ULONG count
, WS_ERROR
*error
)
4315 struct reader
*reader
= (struct reader
*)handle
;
4318 ULONG i
, offset
= 0;
4320 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
4321 if (error
) FIXME( "ignoring error parameter\n" );
4323 if (!reader
) return E_INVALIDARG
;
4325 for (i
= 0; i
< count
; i
++)
4327 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4328 properties
[i
].valueSize
);
4329 if (hr
!= S_OK
) return hr
;
4332 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
4334 switch (encoding
->encodingType
)
4336 case WS_XML_READER_ENCODING_TYPE_TEXT
:
4338 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
4339 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
4340 WS_CHARSET charset
= text
->charSet
;
4342 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
4344 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
4348 if (charset
== WS_CHARSET_AUTO
)
4349 charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
4351 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
4352 &charset
, sizeof(charset
) );
4353 if (hr
!= S_OK
) return hr
;
4357 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4360 switch (input
->inputType
)
4362 case WS_XML_READER_INPUT_TYPE_BUFFER
:
4364 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
4365 set_input_buffer( reader
, NULL
, (const unsigned char *)buf
->encodedData
+ offset
,
4366 buf
->encodedDataSize
- offset
);
4370 FIXME( "input type %u not supported\n", input
->inputType
);
4374 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
4375 read_insert_bof( reader
, node
);
4379 /**************************************************************************
4380 * WsSetInputToBuffer [webservices.@]
4382 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
4383 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
4386 struct reader
*reader
= (struct reader
*)handle
;
4387 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4391 ULONG i
, offset
= 0;
4393 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
4394 if (error
) FIXME( "ignoring error parameter\n" );
4396 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
4398 for (i
= 0; i
< count
; i
++)
4400 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4401 properties
[i
].valueSize
);
4402 if (hr
!= S_OK
) return hr
;
4405 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
4407 charset
= detect_charset( xmlbuf
->ptr
, xmlbuf
->size
, &offset
);
4408 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
4409 &charset
, sizeof(charset
) );
4410 if (hr
!= S_OK
) return hr
;
4412 set_input_buffer( reader
, xmlbuf
, (const unsigned char *)xmlbuf
->ptr
+ offset
, xmlbuf
->size
- offset
);
4413 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
4414 read_insert_bof( reader
, node
);
4418 /**************************************************************************
4419 * WsXmlStringEquals [webservices.@]
4421 HRESULT WINAPI
WsXmlStringEquals( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
, WS_ERROR
*error
)
4423 TRACE( "%s %s %p\n", debugstr_xmlstr(str1
), debugstr_xmlstr(str2
), error
);
4424 if (error
) FIXME( "ignoring error parameter\n" );
4426 if (!str1
|| !str2
) return E_INVALIDARG
;
4428 if (str1
->length
!= str2
->length
) return S_FALSE
;
4429 if (!memcmp( str1
->bytes
, str2
->bytes
, str1
->length
)) return S_OK
;
4433 /**************************************************************************
4434 * WsGetReaderPosition [webservices.@]
4436 HRESULT WINAPI
WsGetReaderPosition( WS_XML_READER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4438 struct reader
*reader
= (struct reader
*)handle
;
4440 TRACE( "%p %p %p\n", handle
, pos
, error
);
4441 if (error
) FIXME( "ignoring error parameter\n" );
4443 if (!reader
|| !pos
) return E_INVALIDARG
;
4444 if (!reader
->input_buf
) return WS_E_INVALID_OPERATION
;
4446 pos
->buffer
= (WS_XML_BUFFER
*)reader
->input_buf
;
4447 pos
->node
= reader
->current
;
4451 /**************************************************************************
4452 * WsSetReaderPosition [webservices.@]
4454 HRESULT WINAPI
WsSetReaderPosition( WS_XML_READER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4456 struct reader
*reader
= (struct reader
*)handle
;
4458 TRACE( "%p %p %p\n", handle
, pos
, error
);
4459 if (error
) FIXME( "ignoring error parameter\n" );
4461 if (!reader
|| !pos
|| (struct xmlbuf
*)pos
->buffer
!= reader
->input_buf
) return E_INVALIDARG
;
4462 if (!reader
->input_buf
) return WS_E_INVALID_OPERATION
;
4464 reader
->current
= pos
->node
;