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
)
1176 dst
[1] = 0x80 | (cp
& 0x3f);
1181 if ((cp
>= 0xd800 && cp
<= 0xdfff) || cp
== 0xfffe || cp
== 0xffff) return -1;
1184 dst
[2] = 0x80 | (cp
& 0x3f);
1186 dst
[1] = 0x80 | (cp
& 0x3f);
1191 dst
[3] = 0x80 | (cp
& 0x3f);
1193 dst
[2] = 0x80 | (cp
& 0x3f);
1195 dst
[1] = 0x80 | (cp
& 0x3f);
1201 static HRESULT
decode_text( const unsigned char *str
, ULONG len
, unsigned char *ret
, ULONG
*ret_len
)
1203 const unsigned char *p
= str
;
1204 unsigned char *q
= ret
;
1212 if (!len
) return WS_E_INVALID_FORMAT
;
1214 if (len
>= 3 && !memcmp( p
, "lt;", 3 ))
1220 else if (len
>= 3 && !memcmp( p
, "gt;", 3 ))
1226 else if (len
>= 5 && !memcmp( p
, "quot;", 5 ))
1232 else if (len
>= 4 && !memcmp( p
, "amp;", 4 ))
1238 else if (len
>= 5 && !memcmp( p
, "apos;", 5 ))
1246 ULONG start
, nb_digits
, i
;
1247 int len_utf8
, cp
= 0;
1250 if (!len
|| *p
!= 'x') return WS_E_INVALID_FORMAT
;
1254 while (len
&& isxdigit( *p
)) { p
++; len
--; };
1255 if (!len
) return WS_E_INVALID_FORMAT
;
1257 p
-= nb_digits
= start
- len
;
1258 if (!nb_digits
|| nb_digits
> 5 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1259 for (i
= 0; i
< nb_digits
; i
++)
1262 if (*p
>= '0' && *p
<= '9') cp
+= *p
- '0';
1263 else if (*p
>= 'a' && *p
<= 'f') cp
+= *p
- 'a' + 10;
1264 else cp
+= *p
- 'A' + 10;
1268 if ((len_utf8
= codepoint_to_utf8( cp
, q
)) < 0) return WS_E_INVALID_FORMAT
;
1269 *ret_len
+= len_utf8
;
1273 else return WS_E_INVALID_FORMAT
;
1285 static HRESULT
read_attribute( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1287 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1288 WS_XML_ATTRIBUTE
*attr
;
1289 WS_XML_UTF8_TEXT
*text
= NULL
;
1290 unsigned int len
= 0, ch
, skip
, quote
;
1291 const unsigned char *start
;
1292 WS_XML_STRING
*prefix
, *localname
;
1293 HRESULT hr
= WS_E_INVALID_FORMAT
;
1295 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1297 start
= read_current_ptr( reader
);
1300 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1301 if (!read_isnamechar( ch
)) break;
1302 read_skip( reader
, skip
);
1305 if (!len
) goto error
;
1307 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1309 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1311 heap_free( prefix
);
1313 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1315 heap_free( localname
);
1318 attr
->localName
= localname
;
1320 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1323 attr
->prefix
= prefix
;
1324 attr
->localName
= localname
;
1328 attr
->prefix
= prefix
;
1329 attr
->localName
= localname
;
1332 hr
= WS_E_INVALID_FORMAT
;
1333 read_skip_whitespace( reader
);
1334 if (read_cmp( reader
, "=", 1 )) goto error
;
1335 read_skip( reader
, 1 );
1337 read_skip_whitespace( reader
);
1338 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) goto error
;
1339 quote
= read_utf8_char( reader
, &skip
);
1340 read_skip( reader
, 1 );
1343 start
= read_current_ptr( reader
);
1346 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1347 if (ch
== quote
) break;
1348 read_skip( reader
, skip
);
1351 read_skip( reader
, 1 );
1356 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1357 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1358 if (!(text
= alloc_utf8_text( NULL
, 0 ))) goto error
;
1362 if (!(text
= alloc_utf8_text( NULL
, len
))) goto error
;
1363 if ((hr
= decode_text( start
, len
, text
->value
.bytes
, &text
->value
.length
)) != S_OK
) goto error
;
1366 attr
->value
= &text
->text
;
1367 attr
->singleQuote
= (quote
== '\'');
1374 free_attribute( attr
);
1378 static inline BOOL
is_valid_parent( const struct node
*node
)
1380 if (!node
) return FALSE
;
1381 return node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
|| node_type( node
) == WS_XML_NODE_TYPE_BOF
;
1384 struct node
*find_parent( struct node
*node
)
1386 if (is_valid_parent( node
)) return node
;
1387 if (is_valid_parent( node
->parent
)) return node
->parent
;
1391 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1393 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1394 const WS_XML_STRING
*ns
;
1397 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1398 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1399 if (!elem
->ns
->length
) elem
->ns
->bytes
= (BYTE
*)(elem
->ns
+ 1); /* quirk */
1401 for (i
= 0; i
< elem
->attributeCount
; i
++)
1403 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1404 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1405 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1406 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1411 static HRESULT
read_element( struct reader
*reader
)
1413 unsigned int len
= 0, ch
, skip
;
1414 const unsigned char *start
;
1415 struct node
*node
= NULL
, *endnode
, *parent
;
1416 WS_XML_ELEMENT_NODE
*elem
;
1417 WS_XML_ATTRIBUTE
*attr
= NULL
;
1418 HRESULT hr
= WS_E_INVALID_FORMAT
;
1420 if (read_end_of_data( reader
))
1422 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1423 reader
->last
= reader
->current
;
1424 reader
->state
= READER_STATE_EOF
;
1428 if (read_cmp( reader
, "<", 1 )) goto error
;
1429 read_skip( reader
, 1 );
1430 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1432 read_rewind( reader
, 1 );
1436 start
= read_current_ptr( reader
);
1439 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1440 if (!read_isnamechar( ch
)) break;
1441 read_skip( reader
, skip
);
1444 if (!len
) goto error
;
1446 if (!(parent
= find_parent( reader
->current
))) goto error
;
1449 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) goto error
;
1450 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) goto error
;
1451 list_add_tail( &node
->children
, &endnode
->entry
);
1452 endnode
->parent
= node
;
1454 elem
= (WS_XML_ELEMENT_NODE
*)node
;
1455 if ((hr
= parse_name( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1457 reader
->current_attr
= 0;
1460 read_skip_whitespace( reader
);
1461 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1462 if ((hr
= read_attribute( reader
, &attr
)) != S_OK
) goto error
;
1463 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1465 free_attribute( attr
);
1468 reader
->current_attr
++;
1470 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1472 read_insert_node( reader
, parent
, node
);
1473 reader
->state
= READER_STATE_STARTELEMENT
;
1477 destroy_nodes( node
);
1481 static HRESULT
read_text( struct reader
*reader
)
1483 unsigned int len
= 0, ch
, skip
;
1484 const unsigned char *start
;
1485 struct node
*node
, *parent
;
1486 WS_XML_TEXT_NODE
*text
;
1487 WS_XML_UTF8_TEXT
*utf8
;
1490 start
= read_current_ptr( reader
);
1493 if (read_end_of_data( reader
)) break;
1494 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1495 if (ch
== '<') break;
1496 read_skip( reader
, skip
);
1500 if (!(parent
= find_parent( reader
->current
))) return WS_E_INVALID_FORMAT
;
1502 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1503 text
= (WS_XML_TEXT_NODE
*)node
;
1504 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
1507 return E_OUTOFMEMORY
;
1509 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1515 text
->text
= &utf8
->text
;
1517 read_insert_node( reader
, parent
, node
);
1518 reader
->state
= READER_STATE_TEXT
;
1522 static HRESULT
read_node( struct reader
* );
1524 static HRESULT
read_startelement( struct reader
*reader
)
1526 read_skip_whitespace( reader
);
1527 if (!read_cmp( reader
, "/>", 2 ))
1529 read_skip( reader
, 2 );
1530 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->children
), struct node
, entry
);
1531 reader
->last
= reader
->current
;
1532 reader
->state
= READER_STATE_ENDELEMENT
;
1535 else if (!read_cmp( reader
, ">", 1 ))
1537 read_skip( reader
, 1 );
1538 return read_node( reader
);
1540 return WS_E_INVALID_FORMAT
;
1543 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
1547 switch (reader
->state
)
1549 case READER_STATE_INITIAL
:
1550 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
1553 case READER_STATE_STARTELEMENT
:
1554 if (found
) *found
= TRUE
;
1561 read_skip_whitespace( reader
);
1562 if ((hr
= read_element( reader
)) == S_OK
&& found
)
1564 if (reader
->state
== READER_STATE_STARTELEMENT
)
1573 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
1576 if (len1
!= len2
) return 1;
1577 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
1581 static struct node
*read_find_startelement( struct reader
*reader
, const WS_XML_STRING
*prefix
,
1582 const WS_XML_STRING
*localname
)
1584 struct node
*parent
;
1585 const WS_XML_STRING
*str
;
1587 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
1589 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1591 str
= parent
->hdr
.prefix
;
1592 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
1593 str
= parent
->hdr
.localName
;
1594 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
1601 static HRESULT
read_endelement( struct reader
*reader
)
1603 struct node
*parent
;
1604 unsigned int len
= 0, ch
, skip
;
1605 const unsigned char *start
;
1606 WS_XML_STRING
*prefix
, *localname
;
1609 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
1611 if (read_end_of_data( reader
))
1613 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1614 reader
->last
= reader
->current
;
1615 reader
->state
= READER_STATE_EOF
;
1619 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
1620 read_skip( reader
, 2 );
1622 start
= read_current_ptr( reader
);
1625 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1628 read_skip( reader
, 1 );
1631 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
1632 read_skip( reader
, skip
);
1636 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
1637 parent
= read_find_startelement( reader
, prefix
, localname
);
1638 heap_free( prefix
);
1639 heap_free( localname
);
1640 if (!parent
) return WS_E_INVALID_FORMAT
;
1642 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
1643 reader
->last
= reader
->current
;
1644 reader
->state
= READER_STATE_ENDELEMENT
;
1648 static HRESULT
read_comment( struct reader
*reader
)
1650 unsigned int len
= 0, ch
, skip
;
1651 const unsigned char *start
;
1652 struct node
*node
, *parent
;
1653 WS_XML_COMMENT_NODE
*comment
;
1655 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
1656 read_skip( reader
, 4 );
1658 start
= read_current_ptr( reader
);
1661 if (!read_cmp( reader
, "-->", 3 ))
1663 read_skip( reader
, 3 );
1666 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1667 read_skip( reader
, skip
);
1671 if (!(parent
= find_parent( reader
->current
))) return WS_E_INVALID_FORMAT
;
1673 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
1674 comment
= (WS_XML_COMMENT_NODE
*)node
;
1675 if (!(comment
->value
.bytes
= heap_alloc( len
)))
1678 return E_OUTOFMEMORY
;
1680 memcpy( comment
->value
.bytes
, start
, len
);
1681 comment
->value
.length
= len
;
1683 read_insert_node( reader
, parent
, node
);
1684 reader
->state
= READER_STATE_COMMENT
;
1688 static HRESULT
read_startcdata( struct reader
*reader
)
1690 struct node
*node
, *endnode
, *parent
;
1692 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
1693 read_skip( reader
, 9 );
1695 if (!(parent
= find_parent( reader
->current
))) return WS_E_INVALID_FORMAT
;
1697 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1698 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
)))
1701 return E_OUTOFMEMORY
;
1703 list_add_tail( &node
->children
, &endnode
->entry
);
1704 endnode
->parent
= node
;
1706 read_insert_node( reader
, parent
, node
);
1707 reader
->state
= READER_STATE_STARTCDATA
;
1711 static HRESULT
read_cdata( struct reader
*reader
)
1713 unsigned int len
= 0, ch
, skip
;
1714 const unsigned char *start
;
1716 WS_XML_TEXT_NODE
*text
;
1717 WS_XML_UTF8_TEXT
*utf8
;
1719 start
= read_current_ptr( reader
);
1722 if (!read_cmp( reader
, "]]>", 3 )) break;
1723 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1724 read_skip( reader
, skip
);
1728 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1729 text
= (WS_XML_TEXT_NODE
*)node
;
1730 if (!(utf8
= alloc_utf8_text( start
, len
)))
1733 return E_OUTOFMEMORY
;
1735 text
->text
= &utf8
->text
;
1737 read_insert_node( reader
, reader
->current
, node
);
1738 reader
->state
= READER_STATE_CDATA
;
1742 static HRESULT
read_endcdata( struct reader
*reader
)
1744 struct node
*parent
;
1746 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
1747 read_skip( reader
, 3 );
1749 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
) parent
= reader
->current
->parent
;
1750 else parent
= reader
->current
;
1752 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
1753 reader
->last
= reader
->current
;
1754 reader
->state
= READER_STATE_ENDCDATA
;
1758 static HRESULT
read_node( struct reader
*reader
)
1764 if (read_end_of_data( reader
))
1766 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1767 reader
->last
= reader
->current
;
1768 reader
->state
= READER_STATE_EOF
;
1771 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
1772 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
1773 else if (!read_cmp( reader
, "<?", 2 ))
1775 hr
= read_xmldecl( reader
);
1776 if (FAILED( hr
)) return hr
;
1778 else if (!read_cmp( reader
, "</", 2 )) return read_endelement( reader
);
1779 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
1780 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment( reader
);
1781 else if (!read_cmp( reader
, "<", 1 )) return read_element( reader
);
1782 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement( reader
);
1783 else return read_text( reader
);
1787 /**************************************************************************
1788 * WsReadEndElement [webservices.@]
1790 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1792 struct reader
*reader
= (struct reader
*)handle
;
1794 TRACE( "%p %p\n", handle
, error
);
1795 if (error
) FIXME( "ignoring error parameter\n" );
1797 if (!reader
) return E_INVALIDARG
;
1798 return read_endelement( reader
);
1801 /**************************************************************************
1802 * WsReadNode [webservices.@]
1804 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
1806 struct reader
*reader
= (struct reader
*)handle
;
1808 TRACE( "%p %p\n", handle
, error
);
1809 if (error
) FIXME( "ignoring error parameter\n" );
1811 if (!reader
) return E_INVALIDARG
;
1812 return read_node( reader
);
1815 /**************************************************************************
1816 * WsReadStartElement [webservices.@]
1818 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1820 struct reader
*reader
= (struct reader
*)handle
;
1822 TRACE( "%p %p\n", handle
, error
);
1823 if (error
) FIXME( "ignoring error parameter\n" );
1825 if (!reader
) return E_INVALIDARG
;
1826 return read_startelement( reader
);
1829 /**************************************************************************
1830 * WsReadToStartElement [webservices.@]
1832 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
1833 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
1835 struct reader
*reader
= (struct reader
*)handle
;
1837 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
1838 if (error
) FIXME( "ignoring error parameter\n" );
1840 if (!reader
) return E_INVALIDARG
;
1841 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
1843 return read_to_startelement( reader
, found
);
1846 BOOL
move_to_root_element( struct node
*root
, struct node
**current
)
1851 if (!(ptr
= list_head( &root
->children
))) return FALSE
;
1852 node
= LIST_ENTRY( ptr
, struct node
, entry
);
1853 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
1858 while ((ptr
= list_next( &root
->children
, &node
->entry
)))
1860 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1861 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1871 BOOL
move_to_next_element( struct node
**current
)
1874 struct node
*node
= *current
, *parent
= (*current
)->parent
;
1876 if (!parent
) return FALSE
;
1877 while ((ptr
= list_next( &parent
->children
, &node
->entry
)))
1879 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1880 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1890 BOOL
move_to_prev_element( struct node
**current
)
1893 struct node
*node
= *current
, *parent
= (*current
)->parent
;
1895 if (!parent
) return FALSE
;
1896 while ((ptr
= list_prev( &parent
->children
, &node
->entry
)))
1898 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
1899 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
1909 BOOL
move_to_child_element( struct node
**current
)
1912 struct node
*child
, *node
= *current
;
1914 if (!(ptr
= list_head( &node
->children
))) return FALSE
;
1915 child
= LIST_ENTRY( ptr
, struct node
, entry
);
1916 if (node_type( child
) == WS_XML_NODE_TYPE_ELEMENT
)
1921 while ((ptr
= list_next( &node
->children
, &child
->entry
)))
1923 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1924 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1934 BOOL
move_to_end_element( struct node
**current
)
1937 struct node
*node
= *current
;
1939 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
1941 if ((ptr
= list_tail( &node
->children
)))
1943 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
1944 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1953 BOOL
move_to_parent_element( struct node
**current
)
1955 struct node
*parent
= (*current
)->parent
;
1957 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
1958 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
1966 BOOL
move_to_first_node( struct node
**current
)
1969 struct node
*node
= *current
;
1971 if ((ptr
= list_head( &node
->parent
->children
)))
1973 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
1979 BOOL
move_to_next_node( struct node
**current
)
1982 struct node
*node
= *current
;
1984 if ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
1986 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
1992 BOOL
move_to_prev_node( struct node
**current
)
1995 struct node
*node
= *current
;
1997 if ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
1999 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2005 BOOL
move_to_bof( struct node
*root
, struct node
**current
)
2011 BOOL
move_to_eof( struct node
*root
, struct node
**current
)
2014 if ((ptr
= list_tail( &root
->children
)))
2016 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2022 BOOL
move_to_child_node( struct node
**current
)
2025 struct node
*node
= *current
;
2027 if ((ptr
= list_head( &node
->children
)))
2029 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2035 BOOL
move_to_parent_node( struct node
**current
)
2037 struct node
*parent
= (*current
)->parent
;
2038 if (!parent
) return FALSE
;
2043 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
2045 BOOL success
= FALSE
;
2048 if (!read_end_of_data( reader
))
2050 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
2051 if (hr
!= S_OK
) return hr
;
2055 case WS_MOVE_TO_ROOT_ELEMENT
:
2056 success
= move_to_root_element( reader
->root
, &reader
->current
);
2059 case WS_MOVE_TO_NEXT_ELEMENT
:
2060 success
= move_to_next_element( &reader
->current
);
2063 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
2064 success
= move_to_prev_element( &reader
->current
);
2067 case WS_MOVE_TO_CHILD_ELEMENT
:
2068 success
= move_to_child_element( &reader
->current
);
2071 case WS_MOVE_TO_END_ELEMENT
:
2072 success
= move_to_end_element( &reader
->current
);
2075 case WS_MOVE_TO_PARENT_ELEMENT
:
2076 success
= move_to_parent_element( &reader
->current
);
2079 case WS_MOVE_TO_FIRST_NODE
:
2080 success
= move_to_first_node( &reader
->current
);
2083 case WS_MOVE_TO_NEXT_NODE
:
2084 success
= move_to_next_node( &reader
->current
);
2087 case WS_MOVE_TO_PREVIOUS_NODE
:
2088 success
= move_to_prev_node( &reader
->current
);
2091 case WS_MOVE_TO_CHILD_NODE
:
2092 success
= move_to_child_node( &reader
->current
);
2095 case WS_MOVE_TO_BOF
:
2096 success
= move_to_bof( reader
->root
, &reader
->current
);
2099 case WS_MOVE_TO_EOF
:
2100 success
= move_to_eof( reader
->root
, &reader
->current
);
2104 FIXME( "unhandled move %u\n", move
);
2113 return success
? S_OK
: WS_E_INVALID_FORMAT
;
2116 /**************************************************************************
2117 * WsMoveReader [webservices.@]
2119 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
2121 struct reader
*reader
= (struct reader
*)handle
;
2123 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
2124 if (error
) FIXME( "ignoring error parameter\n" );
2126 if (!reader
) return E_INVALIDARG
;
2127 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
2129 return read_move_to( reader
, move
, found
);
2132 /**************************************************************************
2133 * WsReadStartAttribute [webservices.@]
2135 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
2137 struct reader
*reader
= (struct reader
*)handle
;
2138 WS_XML_ELEMENT_NODE
*elem
;
2140 TRACE( "%p %u %p\n", handle
, index
, error
);
2141 if (error
) FIXME( "ignoring error parameter\n" );
2143 if (!reader
) return E_INVALIDARG
;
2145 elem
= &reader
->current
->hdr
;
2146 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
2147 return WS_E_INVALID_FORMAT
;
2149 reader
->current_attr
= index
;
2150 reader
->state
= READER_STATE_STARTATTRIBUTE
;
2154 /**************************************************************************
2155 * WsReadEndAttribute [webservices.@]
2157 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
2159 struct reader
*reader
= (struct reader
*)handle
;
2161 TRACE( "%p %p\n", handle
, error
);
2162 if (error
) FIXME( "ignoring error parameter\n" );
2164 if (!reader
) return E_INVALIDARG
;
2166 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
2167 return WS_E_INVALID_FORMAT
;
2169 reader
->state
= READER_STATE_STARTELEMENT
;
2173 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
2177 switch (text
->textType
)
2179 case WS_XML_TEXT_TYPE_UTF8
:
2181 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2182 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
2183 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
2184 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
2189 FIXME( "unhandled type %u\n", text
->textType
);
2196 #define MAX_INT8 0x7f
2197 #define MIN_INT8 (-MAX_INT8 - 1)
2198 #define MAX_INT16 0x7fff
2199 #define MIN_INT16 (-MAX_INT16 - 1)
2200 #define MAX_INT32 0x7fffffff
2201 #define MIN_INT32 (-MAX_INT32 - 1)
2202 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
2203 #define MIN_INT64 (-MAX_INT64 - 1)
2204 #define MAX_UINT8 0xff
2205 #define MAX_UINT16 0xffff
2206 #define MAX_UINT32 0xffffffff
2207 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
2209 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
2211 BOOL negative
= FALSE
;
2212 const unsigned char *ptr
= str
;
2215 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
2216 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
2217 if (!len
) return WS_E_INVALID_FORMAT
;
2225 if (!len
) return WS_E_INVALID_FORMAT
;
2231 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
2233 if (negative
) val
= -val
;
2235 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
2236 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
2238 return WS_E_NUMERIC_OVERFLOW
;
2240 *ret
= *ret
* 10 + val
;
2247 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
2249 const unsigned char *ptr
= str
;
2252 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
2253 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
2254 if (!len
) return WS_E_INVALID_FORMAT
;
2260 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
2263 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
2264 *ret
= *ret
* 10 + val
;
2271 #if defined(__i386__) || defined(__x86_64__)
2273 #define RC_DOWN 0x100;
2274 BOOL
set_fp_rounding( unsigned short *save
)
2277 unsigned short fpword
;
2279 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
2282 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
2285 FIXME( "not implemented\n" );
2289 void restore_fp_rounding( unsigned short fpword
)
2292 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
2294 FIXME( "not implemented\n" );
2298 BOOL
set_fp_rounding( unsigned short *save
)
2300 FIXME( "not implemented\n" );
2303 void restore_fp_rounding( unsigned short fpword
)
2305 FIXME( "not implemented\n" );
2309 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
2311 static const unsigned __int64 nan
= 0xfff8000000000000;
2312 static const unsigned __int64 inf
= 0x7ff0000000000000;
2313 static const unsigned __int64 inf_min
= 0xfff0000000000000;
2314 HRESULT hr
= WS_E_INVALID_FORMAT
;
2315 const unsigned char *p
= str
, *q
;
2316 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
2317 unsigned __int64 val
= 0, tmp
;
2318 long double exp_val
= 1.0, exp_mul
= 10.0;
2319 unsigned short fpword
;
2321 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2322 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2323 if (!len
) return WS_E_INVALID_FORMAT
;
2325 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
2327 *(unsigned __int64
*)ret
= nan
;
2330 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
2332 *(unsigned __int64
*)ret
= inf
;
2335 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
2337 *(unsigned __int64
*)ret
= inf_min
;
2347 else if (*p
== '+') { p
++; len
--; };
2348 if (!len
) return S_OK
;
2350 if (!set_fp_rounding( &fpword
)) return E_NOTIMPL
;
2353 while (len
&& isdigit( *q
)) { q
++; len
--; }
2354 have_digits
= nb_digits
= q
- p
;
2355 for (i
= 0; i
< nb_digits
; i
++)
2357 tmp
= val
* 10 + p
[i
] - '0';
2358 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
2360 for (; i
< nb_digits
; i
++) exp
++;
2371 while (len
&& isdigit( *q
)) { q
++; len
--; };
2372 have_digits
|= nb_digits
= q
- p
;
2373 for (i
= 0; i
< nb_digits
; i
++)
2375 tmp
= val
* 10 + p
[i
] - '0';
2376 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
2381 if (len
> 1 && tolower(*q
) == 'e')
2383 if (!have_digits
) goto done
;
2390 else if (*p
== '+') { p
++; len
--; };
2393 while (len
&& isdigit( *q
)) { q
++; len
--; };
2395 if (!nb_digits
|| len
) goto done
;
2396 for (i
= 0; i
< nb_digits
; i
++)
2398 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
2399 exp_tmp
= MAX_INT32
;
2401 exp_tmp
*= exp_sign
;
2403 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
2404 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
2405 else exp
+= exp_tmp
;
2408 if (!have_digits
|| len
) goto done
;
2410 if ((neg_exp
= exp
< 0)) exp
= -exp
;
2411 for (; exp
; exp
>>= 1)
2413 if (exp
& 1) exp_val
*= exp_mul
;
2417 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
2421 restore_fp_rounding( fpword
);
2425 static HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
2427 static const unsigned char hex
[] =
2429 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
2430 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
2431 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
2432 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
2433 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
2434 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
2435 0,10,11,12,13,14,15 /* 0x60 */
2437 const unsigned char *p
= str
;
2440 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2441 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2442 if (len
!= 36) return WS_E_INVALID_FORMAT
;
2444 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
2445 return WS_E_INVALID_FORMAT
;
2447 for (i
= 0; i
< 36; i
++)
2449 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
2450 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
2453 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
2454 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
2456 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
2457 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
2459 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
2460 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
2461 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
2462 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
2463 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
2464 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
2465 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
2466 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
2471 #define TICKS_PER_SEC 10000000
2472 #define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
2473 #define TICKS_PER_HOUR (3600 * (ULONGLONG)TICKS_PER_SEC)
2474 #define TICKS_PER_DAY (86400 * (ULONGLONG)TICKS_PER_SEC)
2475 #define TICKS_MAX 3155378975999999999
2477 static const int month_offsets
[2][12] =
2479 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
2480 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
2483 static const int month_days
[2][12] =
2485 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
2486 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
2489 static inline int is_leap_year( int year
)
2491 return !(year
% 4) && (year
% 100 || !(year
% 400));
2494 static inline int valid_day( int year
, int month
, int day
)
2496 return day
> 0 && day
<= month_days
[is_leap_year( year
)][month
- 1];
2499 static inline int leap_days_before( int year
)
2501 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
2504 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
2506 const unsigned char *p
= bytes
, *q
;
2507 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
2509 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2510 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2513 while (len
&& isdigit( *q
)) { q
++; len
--; };
2514 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2515 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
2516 if (year
< 1) return WS_E_INVALID_FORMAT
;
2519 while (len
&& isdigit( *q
)) { q
++; len
--; };
2520 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2521 month
= (p
[0] - '0') * 10 + p
[1] - '0';
2522 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
2525 while (len
&& isdigit( *q
)) { q
++; len
--; };
2526 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
2527 day
= (p
[0] - '0') * 10 + p
[1] - '0';
2528 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
2531 while (len
&& isdigit( *q
)) { q
++; len
--; };
2532 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2533 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2534 if (hour
> 24) return WS_E_INVALID_FORMAT
;
2537 while (len
&& isdigit( *q
)) { q
++; len
--; };
2538 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2539 min
= (p
[0] - '0') * 10 + p
[1] - '0';
2540 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2543 while (len
&& isdigit( *q
)) { q
++; len
--; };
2544 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
2545 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
2546 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2550 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
2552 while (len
&& isdigit( *q
)) { q
++; len
--; };
2554 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
2555 for (i
= 0; i
< nb_digits
; i
++)
2557 sec_frac
+= (p
[i
] - '0') * mul
;
2563 if (--len
) return WS_E_INVALID_FORMAT
;
2564 tz_hour
= tz_min
= tz_neg
= 0;
2565 ret
->format
= WS_DATETIME_FORMAT_UTC
;
2567 else if (*q
== '+' || *q
== '-')
2569 tz_neg
= (*q
== '-') ? 1 : 0;
2572 while (len
&& isdigit( *q
)) { q
++; len
--; };
2573 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2574 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2575 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
2578 while (len
&& isdigit( *q
)) { q
++; len
--; };
2579 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
2580 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
2581 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
2583 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
2585 else return WS_E_INVALID_FORMAT
;
2587 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
2588 ret
->ticks
+= month_offsets
[is_leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
2589 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
2590 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
2591 ret
->ticks
+= min
* TICKS_PER_MIN
;
2592 ret
->ticks
+= sec
* TICKS_PER_SEC
;
2593 ret
->ticks
+= sec_frac
;
2597 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
2598 return WS_E_INVALID_FORMAT
;
2599 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
2600 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
2604 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
2605 return WS_E_INVALID_FORMAT
;
2606 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
2607 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
2613 #define TICKS_1601_01_01 504911232000000000
2615 /**************************************************************************
2616 * WsDateTimeToFileTime [webservices.@]
2618 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
2620 unsigned __int64 ticks
;
2622 TRACE( "%p %p %p\n", dt
, ft
, error
);
2623 if (error
) FIXME( "ignoring error parameter\n" );
2625 if (!dt
|| !ft
) return E_INVALIDARG
;
2627 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
2628 ticks
= dt
->ticks
- TICKS_1601_01_01
;
2629 ft
->dwHighDateTime
= ticks
>> 32;
2630 ft
->dwLowDateTime
= (DWORD
)ticks
;
2634 /**************************************************************************
2635 * WsFileTimeToDateTime [webservices.@]
2637 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
2639 unsigned __int64 ticks
;
2641 TRACE( "%p %p %p\n", ft
, dt
, error
);
2642 if (error
) FIXME( "ignoring error parameter\n" );
2644 if (!dt
|| !ft
) return E_INVALIDARG
;
2646 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
2647 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
2648 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
2649 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
2650 dt
->format
= WS_DATETIME_FORMAT_UTC
;
2654 static HRESULT
read_get_node_text( struct reader
*reader
, WS_XML_UTF8_TEXT
**ret
)
2656 WS_XML_TEXT_NODE
*text
;
2658 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
2659 return WS_E_INVALID_FORMAT
;
2661 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
2662 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2664 FIXME( "text type %u not supported\n", text
->text
->textType
);
2667 *ret
= (WS_XML_UTF8_TEXT
*)text
->text
;
2671 static HRESULT
read_get_attribute_text( struct reader
*reader
, ULONG index
, WS_XML_UTF8_TEXT
**ret
)
2673 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2674 WS_XML_ATTRIBUTE
*attr
;
2676 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2677 return WS_E_INVALID_FORMAT
;
2679 attr
= elem
->attributes
[index
];
2680 if (attr
->value
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2682 FIXME( "text type %u not supported\n", attr
->value
->textType
);
2685 *ret
= (WS_XML_UTF8_TEXT
*)attr
->value
;
2689 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
2690 const WS_XML_STRING
*ns
, ULONG
*index
)
2693 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2697 *index
= reader
->current_attr
;
2700 for (i
= 0; i
< elem
->attributeCount
; i
++)
2702 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
2703 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
2705 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
2706 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
2715 /**************************************************************************
2716 * WsFindAttribute [webservices.@]
2718 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2719 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
2722 struct reader
*reader
= (struct reader
*)handle
;
2724 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
2725 required
, index
, error
);
2726 if (error
) FIXME( "ignoring error parameter\n" );
2728 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
2730 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2731 return WS_E_INVALID_OPERATION
;
2733 if (!find_attribute( reader
, localname
, ns
, index
))
2735 if (required
) return WS_E_INVALID_FORMAT
;
2742 static HRESULT
read_get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2743 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2744 WS_XML_UTF8_TEXT
**ret
, BOOL
*found
)
2748 case WS_ATTRIBUTE_TYPE_MAPPING
:
2751 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
2752 return read_get_attribute_text( reader
, index
, ret
);
2754 case WS_ELEMENT_TYPE_MAPPING
:
2755 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2756 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2762 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2764 if (WsXmlStringEquals( localname
, elem
->localName
, NULL
) != S_OK
||
2765 WsXmlStringEquals( ns
, elem
->ns
, NULL
) != S_OK
)
2770 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
2772 return read_get_node_text( reader
, ret
);
2775 FIXME( "mapping %u not supported\n", mapping
);
2780 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2781 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2782 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2783 WS_HEAP
*heap
, void *ret
, ULONG size
)
2785 WS_XML_UTF8_TEXT
*utf8
;
2787 BOOL found
, val
= FALSE
;
2791 FIXME( "description not supported\n" );
2794 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2797 ULONG len
= utf8
->value
.length
;
2798 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
2799 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
2800 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
2801 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
2802 else return WS_E_INVALID_FORMAT
;
2807 case WS_READ_REQUIRED_VALUE
:
2808 if (!found
) return WS_E_INVALID_FORMAT
;
2809 if (size
!= sizeof(BOOL
)) return E_INVALIDARG
;
2813 case WS_READ_REQUIRED_POINTER
:
2814 if (!found
) return WS_E_INVALID_FORMAT
;
2817 case WS_READ_OPTIONAL_POINTER
:
2819 BOOL
*heap_val
= NULL
;
2820 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2823 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2826 *(BOOL
**)ret
= heap_val
;
2830 FIXME( "read option %u not supported\n", option
);
2837 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2838 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2839 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2840 WS_HEAP
*heap
, void *ret
, ULONG size
)
2842 WS_XML_UTF8_TEXT
*utf8
;
2849 FIXME( "description not supported\n" );
2852 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2853 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
2858 case WS_READ_REQUIRED_VALUE
:
2859 if (!found
) return WS_E_INVALID_FORMAT
;
2860 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
2864 case WS_READ_REQUIRED_POINTER
:
2865 if (!found
) return WS_E_INVALID_FORMAT
;
2868 case WS_READ_OPTIONAL_POINTER
:
2870 INT8
*heap_val
= NULL
;
2871 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2874 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2877 *(INT8
**)ret
= heap_val
;
2881 FIXME( "read option %u not supported\n", option
);
2888 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2889 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2890 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2891 WS_HEAP
*heap
, void *ret
, ULONG size
)
2893 WS_XML_UTF8_TEXT
*utf8
;
2900 FIXME( "description not supported\n" );
2903 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2904 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
2909 case WS_READ_REQUIRED_VALUE
:
2910 if (!found
) return WS_E_INVALID_FORMAT
;
2911 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
2912 *(INT16
*)ret
= val
;
2915 case WS_READ_REQUIRED_POINTER
:
2916 if (!found
) return WS_E_INVALID_FORMAT
;
2919 case WS_READ_OPTIONAL_POINTER
:
2921 INT16
*heap_val
= NULL
;
2922 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2925 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2928 *(INT16
**)ret
= heap_val
;
2932 FIXME( "read option %u not supported\n", option
);
2939 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2940 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2941 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2942 WS_HEAP
*heap
, void *ret
, ULONG size
)
2944 WS_XML_UTF8_TEXT
*utf8
;
2951 FIXME( "description not supported\n" );
2954 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2955 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
2960 case WS_READ_REQUIRED_VALUE
:
2961 if (!found
) return WS_E_INVALID_FORMAT
;
2962 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
2963 *(INT32
*)ret
= val
;
2966 case WS_READ_REQUIRED_POINTER
:
2967 if (!found
) return WS_E_INVALID_FORMAT
;
2970 case WS_READ_OPTIONAL_POINTER
:
2972 INT32
*heap_val
= NULL
;
2973 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2976 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2979 *(INT32
**)ret
= heap_val
;
2983 FIXME( "read option %u not supported\n", option
);
2990 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2991 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2992 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2993 WS_HEAP
*heap
, void *ret
, ULONG size
)
2995 WS_XML_UTF8_TEXT
*utf8
;
3002 FIXME( "description not supported\n" );
3005 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3006 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
3011 case WS_READ_REQUIRED_VALUE
:
3012 if (!found
) return WS_E_INVALID_FORMAT
;
3013 if (size
!= sizeof(INT64
)) return E_INVALIDARG
;
3014 *(INT64
*)ret
= val
;
3017 case WS_READ_REQUIRED_POINTER
:
3018 if (!found
) return WS_E_INVALID_FORMAT
;
3021 case WS_READ_OPTIONAL_POINTER
:
3023 INT64
*heap_val
= NULL
;
3024 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3027 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3030 *(INT64
**)ret
= heap_val
;
3034 FIXME( "read option %u not supported\n", option
);
3041 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3042 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3043 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3044 WS_HEAP
*heap
, void *ret
, ULONG size
)
3046 WS_XML_UTF8_TEXT
*utf8
;
3053 FIXME( "description not supported\n" );
3056 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3057 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
3062 case WS_READ_REQUIRED_VALUE
:
3063 if (!found
) return WS_E_INVALID_FORMAT
;
3064 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
3065 *(UINT8
*)ret
= val
;
3068 case WS_READ_REQUIRED_POINTER
:
3069 if (!found
) return WS_E_INVALID_FORMAT
;
3072 case WS_READ_OPTIONAL_POINTER
:
3074 UINT8
*heap_val
= NULL
;
3075 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3078 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3081 *(UINT8
**)ret
= heap_val
;
3085 FIXME( "read option %u not supported\n", option
);
3092 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3093 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3094 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3095 WS_HEAP
*heap
, void *ret
, ULONG size
)
3097 WS_XML_UTF8_TEXT
*utf8
;
3104 FIXME( "description not supported\n" );
3107 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3108 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
3113 case WS_READ_REQUIRED_VALUE
:
3114 if (!found
) return WS_E_INVALID_FORMAT
;
3115 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
3116 *(UINT16
*)ret
= val
;
3119 case WS_READ_REQUIRED_POINTER
:
3120 if (!found
) return WS_E_INVALID_FORMAT
;
3123 case WS_READ_OPTIONAL_POINTER
:
3125 UINT16
*heap_val
= NULL
;
3126 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3129 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3132 *(UINT16
**)ret
= heap_val
;
3136 FIXME( "read option %u not supported\n", option
);
3143 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3144 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3145 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3146 WS_HEAP
*heap
, void *ret
, ULONG size
)
3148 WS_XML_UTF8_TEXT
*utf8
;
3155 FIXME( "description not supported\n" );
3158 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3159 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
3164 case WS_READ_REQUIRED_VALUE
:
3165 if (!found
) return WS_E_INVALID_FORMAT
;
3166 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
3167 *(UINT32
*)ret
= val
;
3170 case WS_READ_REQUIRED_POINTER
:
3171 if (!found
) return WS_E_INVALID_FORMAT
;
3174 case WS_READ_OPTIONAL_POINTER
:
3176 UINT32
*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 *(UINT32
**)ret
= heap_val
;
3187 FIXME( "read option %u not supported\n", option
);
3194 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3195 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3196 const WS_UINT64_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_UINT64
, &val
)) != S_OK
)
3215 case WS_READ_REQUIRED_VALUE
:
3216 if (!found
) return WS_E_INVALID_FORMAT
;
3217 if (size
!= sizeof(UINT64
)) return E_INVALIDARG
;
3218 *(UINT64
*)ret
= val
;
3221 case WS_READ_REQUIRED_POINTER
:
3222 if (!found
) return WS_E_INVALID_FORMAT
;
3225 case WS_READ_OPTIONAL_POINTER
:
3227 UINT64
*heap_val
= NULL
;
3228 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3231 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3234 *(UINT64
**)ret
= heap_val
;
3238 FIXME( "read option %u not supported\n", option
);
3245 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3246 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3247 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3248 WS_HEAP
*heap
, void *ret
, ULONG size
)
3250 WS_XML_UTF8_TEXT
*utf8
;
3255 if (desc
) FIXME( "ignoring description\n" );
3257 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3258 if (found
&& (hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3262 case WS_READ_REQUIRED_VALUE
:
3263 if (!found
) return WS_E_INVALID_FORMAT
;
3264 if (size
!= sizeof(double)) return E_INVALIDARG
;
3265 *(double *)ret
= val
;
3268 case WS_READ_REQUIRED_POINTER
:
3269 if (!found
) return WS_E_INVALID_FORMAT
;
3272 case WS_READ_OPTIONAL_POINTER
:
3274 double *heap_val
= NULL
;
3275 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3278 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3281 *(double **)ret
= heap_val
;
3285 FIXME( "read option %u not supported\n", option
);
3292 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3293 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3294 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3295 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
3297 WS_XML_UTF8_TEXT
*utf8
;
3304 FIXME( "description not supported\n" );
3307 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3308 if (found
&& !(str
= xmltext_to_widechar( heap
, &utf8
->text
))) return WS_E_QUOTA_EXCEEDED
;
3312 case WS_READ_REQUIRED_POINTER
:
3313 if (!found
) return WS_E_INVALID_FORMAT
;
3316 case WS_READ_OPTIONAL_POINTER
:
3317 if (size
!= sizeof(str
)) return E_INVALIDARG
;
3322 FIXME( "read option %u not supported\n", option
);
3329 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
3332 for (i
= 0; i
< desc
->valueCount
; i
++)
3334 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
3336 *ret
= desc
->values
[i
].value
;
3340 return WS_E_INVALID_FORMAT
;
3343 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3344 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3345 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3346 WS_HEAP
*heap
, void *ret
, ULONG size
)
3348 WS_XML_UTF8_TEXT
*utf8
;
3353 if (!desc
) return E_INVALIDARG
;
3355 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3356 if (found
&& (hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
3360 case WS_READ_REQUIRED_VALUE
:
3361 if (!found
) return WS_E_INVALID_FORMAT
;
3362 if (size
!= sizeof(int)) return E_INVALIDARG
;
3366 case WS_READ_REQUIRED_POINTER
:
3367 if (!found
) return WS_E_INVALID_FORMAT
;
3370 case WS_READ_OPTIONAL_POINTER
:
3372 int *heap_val
= NULL
;
3373 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3376 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3379 *(int **)ret
= heap_val
;
3383 FIXME( "read option %u not supported\n", option
);
3390 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3391 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3392 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3393 WS_HEAP
*heap
, void *ret
, ULONG size
)
3395 WS_XML_UTF8_TEXT
*utf8
;
3397 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
3400 if (desc
) FIXME( "ignoring description\n" );
3402 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3403 if (found
&& (hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3407 case WS_READ_REQUIRED_VALUE
:
3408 if (!found
) return WS_E_INVALID_FORMAT
;
3409 if (size
!= sizeof(WS_DATETIME
)) return E_INVALIDARG
;
3410 *(WS_DATETIME
*)ret
= val
;
3413 case WS_READ_REQUIRED_POINTER
:
3414 if (!found
) return WS_E_INVALID_FORMAT
;
3417 case WS_READ_OPTIONAL_POINTER
:
3419 WS_DATETIME
*heap_val
= NULL
;
3420 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3423 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3426 *(WS_DATETIME
**)ret
= heap_val
;
3430 FIXME( "read option %u not supported\n", option
);
3437 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3438 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3439 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3440 WS_HEAP
*heap
, void *ret
, ULONG size
)
3442 WS_XML_UTF8_TEXT
*utf8
;
3447 if (desc
) FIXME( "ignoring description\n" );
3449 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3450 if (found
&& (hr
= str_to_guid( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3454 case WS_READ_REQUIRED_VALUE
:
3455 if (!found
) return WS_E_INVALID_FORMAT
;
3456 if (size
!= sizeof(GUID
)) return E_INVALIDARG
;
3460 case WS_READ_REQUIRED_POINTER
:
3461 if (!found
) return WS_E_INVALID_FORMAT
;
3464 case WS_READ_OPTIONAL_POINTER
:
3466 GUID
*heap_val
= NULL
;
3467 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3470 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3473 *(GUID
**)ret
= heap_val
;
3477 FIXME( "read option %u not supported\n", option
);
3484 static BOOL
is_empty_text_node( const struct node
*node
)
3486 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
3487 const WS_XML_UTF8_TEXT
*utf8
;
3490 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
3491 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3493 ERR( "unhandled text type %u\n", text
->text
->textType
);
3496 utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
3497 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
3501 static HRESULT
read_next_node( struct reader
*reader
)
3503 if (reader
->current
== reader
->last
) return read_node( reader
);
3504 if (move_to_child_node( &reader
->current
)) return S_OK
;
3505 if (move_to_next_node( &reader
->current
)) return S_OK
;
3506 if (!move_to_parent_node( &reader
->current
)) return WS_E_INVALID_FORMAT
;
3507 if (move_to_next_node( &reader
->current
)) return S_OK
;
3508 return WS_E_INVALID_FORMAT
;
3511 /* skips comment and empty text nodes */
3512 static HRESULT
read_type_next_node( struct reader
*reader
)
3517 WS_XML_NODE_TYPE type
;
3519 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3520 type
= node_type( reader
->current
);
3521 if (type
== WS_XML_NODE_TYPE_COMMENT
||
3522 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
3527 static BOOL
match_current_element( struct reader
*reader
, const WS_XML_STRING
*localname
,
3528 const WS_XML_STRING
*ns
)
3530 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3531 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
3532 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
3533 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
3536 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
3537 const WS_XML_STRING
*ns
)
3543 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
3544 if (reader
->current
== reader
->last
)
3547 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
3548 if (!found
) return WS_E_INVALID_FORMAT
;
3550 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3552 node
= reader
->current
;
3553 attr
= reader
->current_attr
;
3555 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
3556 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3558 reader
->current
= node
;
3559 reader
->current_attr
= attr
;
3561 return WS_E_INVALID_FORMAT
;
3564 static ULONG
get_type_size( WS_TYPE type
, const WS_STRUCT_DESCRIPTION
*desc
)
3570 return sizeof(INT8
);
3573 case WS_UINT16_TYPE
:
3574 return sizeof(INT16
);
3578 case WS_UINT32_TYPE
:
3580 return sizeof(INT32
);
3583 case WS_UINT64_TYPE
:
3584 return sizeof(INT64
);
3586 case WS_DOUBLE_TYPE
:
3587 return sizeof(double);
3589 case WS_DATETIME_TYPE
:
3590 return sizeof(WS_DATETIME
);
3593 return sizeof(GUID
);
3596 return sizeof(WCHAR
*);
3598 case WS_STRUCT_TYPE
:
3602 ERR( "unhandled type %u\n", type
);
3607 static WS_READ_OPTION
get_array_read_option( WS_TYPE type
)
3617 case WS_UINT16_TYPE
:
3618 case WS_UINT32_TYPE
:
3619 case WS_UINT64_TYPE
:
3620 case WS_DOUBLE_TYPE
:
3622 case WS_STRUCT_TYPE
:
3623 case WS_DATETIME_TYPE
:
3625 return WS_READ_REQUIRED_VALUE
;
3628 return WS_READ_REQUIRED_POINTER
;
3631 FIXME( "unhandled type %u\n", type
);
3636 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
3637 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
3640 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3641 WS_HEAP
*heap
, void **ret
, ULONG size
, ULONG
*count
)
3644 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
3645 WS_READ_OPTION option
;
3648 if (size
!= sizeof(void *) || !(option
= get_array_read_option( desc
->type
))) return E_INVALIDARG
;
3650 /* wrapper element */
3651 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
3654 if (option
== WS_READ_REQUIRED_VALUE
)
3655 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
3657 item_size
= sizeof(void *);
3659 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
3662 if (nb_items
>= nb_allocated
)
3664 if (!(buf
= ws_realloc_zero( heap
, buf
, nb_allocated
* 2 * item_size
)))
3665 return WS_E_QUOTA_EXCEEDED
;
3668 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
3669 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
3670 if (hr
== WS_E_INVALID_FORMAT
) break;
3673 ws_free( heap
, buf
);
3676 offset
+= item_size
;
3680 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
3682 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
3684 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
3685 desc
->itemRange
->maxItemCount
);
3686 ws_free( heap
, buf
);
3687 return WS_E_INVALID_FORMAT
;
3696 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3697 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
3700 if (reader
->current
== reader
->last
)
3703 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
3704 if (!found
) return WS_E_INVALID_FORMAT
;
3706 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3707 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
3709 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
3710 desc
->typeDescription
, option
, heap
, ret
, size
);
3713 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
)
3723 case WS_UINT16_TYPE
:
3724 case WS_UINT32_TYPE
:
3725 case WS_UINT64_TYPE
:
3726 case WS_DOUBLE_TYPE
:
3728 case WS_DATETIME_TYPE
:
3730 return WS_READ_REQUIRED_VALUE
;
3733 case WS_STRUCT_TYPE
:
3734 return WS_READ_REQUIRED_POINTER
;
3737 FIXME( "unhandled type %u\n", type
);
3742 static HRESULT
read_type_struct_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3743 WS_HEAP
*heap
, char *buf
)
3746 WS_READ_OPTION option
;
3750 if (!desc
) return E_INVALIDARG
;
3751 if (desc
->options
& ~(WS_FIELD_POINTER
| WS_FIELD_OPTIONAL
))
3753 FIXME( "options %08x not supported\n", desc
->options
);
3756 if (!(option
= get_field_read_option( desc
->type
))) return E_INVALIDARG
;
3758 if (option
== WS_READ_REQUIRED_VALUE
)
3759 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3761 size
= sizeof(void *);
3763 ptr
= buf
+ desc
->offset
;
3764 switch (desc
->mapping
)
3766 case WS_ATTRIBUTE_FIELD_MAPPING
:
3767 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
3768 desc
->typeDescription
, option
, heap
, ptr
, size
);
3771 case WS_ELEMENT_FIELD_MAPPING
:
3772 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
3773 desc
->typeDescription
, option
, heap
, ptr
, size
);
3776 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3779 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, size
, &count
);
3780 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
3783 case WS_TEXT_FIELD_MAPPING
:
3784 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
3788 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
3792 if (hr
== WS_E_INVALID_FORMAT
&& desc
->options
& WS_FIELD_OPTIONAL
)
3796 case WS_READ_REQUIRED_VALUE
:
3797 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
3798 else memset( ptr
, 0, size
);
3801 case WS_READ_REQUIRED_POINTER
:
3802 *(void **)ptr
= NULL
;
3806 ERR( "unhandled option %u\n", option
);
3814 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3815 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3816 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3817 WS_HEAP
*heap
, void *ret
, ULONG size
)
3823 if (!desc
) return E_INVALIDARG
;
3824 if (desc
->structOptions
) FIXME( "struct options %08x not supported\n", desc
->structOptions
);
3828 case WS_READ_REQUIRED_POINTER
:
3829 case WS_READ_OPTIONAL_POINTER
:
3830 if (size
!= sizeof(void *)) return E_INVALIDARG
;
3831 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
3834 case WS_READ_REQUIRED_VALUE
:
3835 if (size
!= desc
->size
) return E_INVALIDARG
;
3840 FIXME( "unhandled read option %u\n", option
);
3844 for (i
= 0; i
< desc
->fieldCount
; i
++)
3846 if ((hr
= read_type_struct_field( reader
, desc
->fields
[i
], heap
, buf
)) != S_OK
)
3852 case WS_READ_REQUIRED_POINTER
:
3855 ws_free( heap
, buf
);
3858 *(char **)ret
= buf
;
3861 case WS_READ_OPTIONAL_POINTER
:
3864 ws_free( heap
, buf
);
3867 *(char **)ret
= buf
;
3870 case WS_READ_REQUIRED_VALUE
:
3874 ERR( "unhandled read option %u\n", option
);
3879 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3880 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3881 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
,
3882 void *value
, ULONG size
)
3888 case WS_ELEMENT_TYPE_MAPPING
:
3889 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3890 if ((hr
= read_type_next_element_node( reader
, localname
, ns
)) != S_OK
) return hr
;
3893 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3894 case WS_ATTRIBUTE_TYPE_MAPPING
:
3898 FIXME( "unhandled mapping %u\n", mapping
);
3904 case WS_STRUCT_TYPE
:
3905 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3910 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3915 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3920 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3925 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3930 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3935 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3939 case WS_UINT16_TYPE
:
3940 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3944 case WS_UINT32_TYPE
:
3945 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3949 case WS_UINT64_TYPE
:
3950 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3954 case WS_DOUBLE_TYPE
:
3955 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3960 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3965 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3969 case WS_DATETIME_TYPE
:
3970 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3975 if ((hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3980 FIXME( "type %u not supported\n", type
);
3986 case WS_ELEMENT_TYPE_MAPPING
:
3987 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3988 return read_type_next_node( reader
);
3990 case WS_ATTRIBUTE_TYPE_MAPPING
:
3996 /**************************************************************************
3997 * WsReadType [webservices.@]
3999 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
4000 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
4001 ULONG size
, WS_ERROR
*error
)
4003 struct reader
*reader
= (struct reader
*)handle
;
4006 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
4008 if (error
) FIXME( "ignoring error parameter\n" );
4010 if (!reader
|| !value
) return E_INVALIDARG
;
4012 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
4017 case WS_ELEMENT_TYPE_MAPPING
:
4018 if ((hr
= read_node( reader
)) != S_OK
) return hr
;
4025 if (!read_end_of_data( reader
)) return WS_E_INVALID_FORMAT
;
4029 /**************************************************************************
4030 * WsReadElement [webservices.@]
4032 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4033 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
4036 struct reader
*reader
= (struct reader
*)handle
;
4038 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
4039 if (error
) FIXME( "ignoring error parameter\n" );
4041 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
4043 return read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
4044 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
4047 /**************************************************************************
4048 * WsReadValue [webservices.@]
4050 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
4053 struct reader
*reader
= (struct reader
*)handle
;
4054 WS_TYPE type
= map_value_type( value_type
);
4056 TRACE( "%p %u %p %u %p\n", handle
, type
, value
, size
, error
);
4057 if (error
) FIXME( "ignoring error parameter\n" );
4059 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
4061 return read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
4062 NULL
, value
, size
);
4065 /**************************************************************************
4066 * WsSetErrorProperty [webservices.@]
4068 HRESULT WINAPI
WsSetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, const void *value
,
4071 struct error
*error
= (struct error
*)handle
;
4073 TRACE( "%p %u %p %u\n", handle
, id
, value
, size
);
4075 if (id
== WS_ERROR_PROPERTY_LANGID
) return WS_E_INVALID_OPERATION
;
4076 return prop_set( error
->prop
, error
->prop_count
, id
, value
, size
);
4079 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
4081 static const char bom
[] = {0xef,0xbb,0xbf};
4082 const unsigned char *p
= data
;
4084 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
4085 (size
> 2 && !(*offset
= 0));
4088 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
4090 static const char bom
[] = {0xff,0xfe};
4091 const unsigned char *p
= data
;
4093 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
4094 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
4097 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
4101 /* FIXME: parse xml declaration */
4103 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
4104 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
4107 FIXME( "charset not recognized\n" );
4111 TRACE( "detected charset %u\n", ret
);
4115 static void set_input_buffer( struct reader
*reader
, struct xmlbuf
*buf
, const unsigned char *data
, ULONG size
)
4117 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
4118 reader
->input_buf
= buf
;
4119 reader
->input_data
= data
;
4120 reader
->input_size
= size
;
4122 reader
->read_size
= reader
->input_size
;
4123 reader
->read_pos
= 0;
4124 reader
->read_bufptr
= reader
->input_data
;
4127 /**************************************************************************
4128 * WsSetInput [webservices.@]
4130 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
4131 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
4132 ULONG count
, WS_ERROR
*error
)
4134 struct reader
*reader
= (struct reader
*)handle
;
4137 ULONG i
, offset
= 0;
4139 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
4140 if (error
) FIXME( "ignoring error parameter\n" );
4142 if (!reader
) return E_INVALIDARG
;
4144 for (i
= 0; i
< count
; i
++)
4146 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4147 properties
[i
].valueSize
);
4148 if (hr
!= S_OK
) return hr
;
4151 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
4153 switch (encoding
->encodingType
)
4155 case WS_XML_READER_ENCODING_TYPE_TEXT
:
4157 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
4158 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
4159 WS_CHARSET charset
= text
->charSet
;
4161 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
4163 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
4167 if (charset
== WS_CHARSET_AUTO
)
4168 charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
4170 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
4171 &charset
, sizeof(charset
) );
4172 if (hr
!= S_OK
) return hr
;
4176 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4179 switch (input
->inputType
)
4181 case WS_XML_READER_INPUT_TYPE_BUFFER
:
4183 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
4184 set_input_buffer( reader
, NULL
, (const unsigned char *)buf
->encodedData
+ offset
,
4185 buf
->encodedDataSize
- offset
);
4189 FIXME( "input type %u not supported\n", input
->inputType
);
4193 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
4194 read_insert_bof( reader
, node
);
4198 /**************************************************************************
4199 * WsSetInputToBuffer [webservices.@]
4201 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
4202 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
4205 struct reader
*reader
= (struct reader
*)handle
;
4206 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4210 ULONG i
, offset
= 0;
4212 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
4213 if (error
) FIXME( "ignoring error parameter\n" );
4215 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
4217 for (i
= 0; i
< count
; i
++)
4219 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4220 properties
[i
].valueSize
);
4221 if (hr
!= S_OK
) return hr
;
4224 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
4226 charset
= detect_charset( xmlbuf
->ptr
, xmlbuf
->size
, &offset
);
4227 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
4228 &charset
, sizeof(charset
) );
4229 if (hr
!= S_OK
) return hr
;
4231 set_input_buffer( reader
, xmlbuf
, (const unsigned char *)xmlbuf
->ptr
+ offset
, xmlbuf
->size
- offset
);
4232 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
4233 read_insert_bof( reader
, node
);
4237 /**************************************************************************
4238 * WsXmlStringEquals [webservices.@]
4240 HRESULT WINAPI
WsXmlStringEquals( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
, WS_ERROR
*error
)
4242 TRACE( "%s %s %p\n", debugstr_xmlstr(str1
), debugstr_xmlstr(str2
), error
);
4243 if (error
) FIXME( "ignoring error parameter\n" );
4245 if (!str1
|| !str2
) return E_INVALIDARG
;
4247 if (str1
->length
!= str2
->length
) return S_FALSE
;
4248 if (!memcmp( str1
->bytes
, str2
->bytes
, str1
->length
)) return S_OK
;
4252 /**************************************************************************
4253 * WsGetReaderPosition [webservices.@]
4255 HRESULT WINAPI
WsGetReaderPosition( WS_XML_READER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4257 struct reader
*reader
= (struct reader
*)handle
;
4259 TRACE( "%p %p %p\n", handle
, pos
, error
);
4260 if (error
) FIXME( "ignoring error parameter\n" );
4262 if (!reader
|| !pos
) return E_INVALIDARG
;
4263 if (!reader
->input_buf
) return WS_E_INVALID_OPERATION
;
4265 pos
->buffer
= (WS_XML_BUFFER
*)reader
->input_buf
;
4266 pos
->node
= reader
->current
;
4270 /**************************************************************************
4271 * WsSetReaderPosition [webservices.@]
4273 HRESULT WINAPI
WsSetReaderPosition( WS_XML_READER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4275 struct reader
*reader
= (struct reader
*)handle
;
4277 TRACE( "%p %p %p\n", handle
, pos
, error
);
4278 if (error
) FIXME( "ignoring error parameter\n" );
4280 if (!reader
|| !pos
|| (struct xmlbuf
*)pos
->buffer
!= reader
->input_buf
) return E_INVALIDARG
;
4281 if (!reader
->input_buf
) return WS_E_INVALID_OPERATION
;
4283 reader
->current
= pos
->node
;