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 const struct prop_desc reader_props
[] =
383 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
384 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
385 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
386 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
387 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
388 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
389 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
390 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
391 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
392 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
393 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
394 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
395 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
396 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
397 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
402 READER_STATE_INITIAL
,
404 READER_STATE_STARTELEMENT
,
405 READER_STATE_STARTATTRIBUTE
,
406 READER_STATE_STARTCDATA
,
409 READER_STATE_ENDELEMENT
,
410 READER_STATE_ENDCDATA
,
411 READER_STATE_COMMENT
,
425 const unsigned char *read_bufptr
;
426 enum reader_state state
;
428 struct node
*current
;
431 struct prefix
*prefixes
;
433 ULONG nb_prefixes_allocated
;
434 WS_XML_READER_INPUT_TYPE input_type
;
435 const unsigned char *input_data
;
438 struct prop prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
441 static struct reader
*alloc_reader(void)
443 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
445 ULONG size
= sizeof(*ret
) + prop_size( reader_props
, count
);
447 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
448 if (!(ret
->prefixes
= heap_alloc_zero( sizeof(*ret
->prefixes
) )))
453 ret
->nb_prefixes
= ret
->nb_prefixes_allocated
= 1;
455 prop_init( reader_props
, count
, ret
->prop
, &ret
[1] );
456 ret
->prop_count
= count
;
460 static void clear_prefixes( struct prefix
*prefixes
, ULONG count
)
463 for (i
= 0; i
< count
; i
++)
465 heap_free( prefixes
[i
].str
.bytes
);
466 prefixes
[i
].str
.bytes
= NULL
;
467 prefixes
[i
].str
.length
= 0;
469 heap_free( prefixes
[i
].ns
.bytes
);
470 prefixes
[i
].ns
.bytes
= NULL
;
471 prefixes
[i
].ns
.length
= 0;
475 static void free_reader( struct reader
*reader
)
478 destroy_nodes( reader
->root
);
479 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
480 heap_free( reader
->prefixes
);
484 static HRESULT
set_prefix( struct prefix
*prefix
, const WS_XML_STRING
*str
, const WS_XML_STRING
*ns
)
488 heap_free( prefix
->str
.bytes
);
489 if (!(prefix
->str
.bytes
= heap_alloc( str
->length
))) return E_OUTOFMEMORY
;
490 memcpy( prefix
->str
.bytes
, str
->bytes
, str
->length
);
491 prefix
->str
.length
= str
->length
;
494 heap_free( prefix
->ns
.bytes
);
495 if (!(prefix
->ns
.bytes
= heap_alloc( ns
->length
))) return E_OUTOFMEMORY
;
496 memcpy( prefix
->ns
.bytes
, ns
->bytes
, ns
->length
);
497 prefix
->ns
.length
= ns
->length
;
502 static HRESULT
bind_prefix( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
*ns
)
507 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
509 if (WsXmlStringEquals( prefix
, &reader
->prefixes
[i
].str
, NULL
) == S_OK
)
510 return set_prefix( &reader
->prefixes
[i
], NULL
, ns
);
512 if (i
>= reader
->nb_prefixes_allocated
)
514 ULONG new_size
= reader
->nb_prefixes_allocated
* sizeof(*reader
->prefixes
) * 2;
515 struct prefix
*tmp
= heap_realloc_zero( reader
->prefixes
, new_size
);
516 if (!tmp
) return E_OUTOFMEMORY
;
517 reader
->prefixes
= tmp
;
518 reader
->nb_prefixes_allocated
*= 2;
521 if ((hr
= set_prefix( &reader
->prefixes
[i
], prefix
, ns
)) != S_OK
) return hr
;
522 reader
->nb_prefixes
++;
526 static const WS_XML_STRING
*get_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
)
529 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
531 if (WsXmlStringEquals( prefix
, &reader
->prefixes
[i
].str
, NULL
) == S_OK
)
532 return &reader
->prefixes
[i
].ns
;
537 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
539 if (!reader
->root
) reader
->root
= eof
;
542 eof
->parent
= reader
->root
;
543 list_add_tail( &reader
->root
->children
, &eof
->entry
);
545 reader
->current
= reader
->last
= eof
;
548 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
550 reader
->root
->parent
= bof
;
551 list_add_tail( &bof
->children
, &reader
->root
->entry
);
552 reader
->current
= reader
->last
= reader
->root
= bof
;
555 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
557 node
->parent
= parent
;
558 if (node
->parent
== reader
->root
)
560 struct list
*eof
= list_tail( &reader
->root
->children
);
561 list_add_before( eof
, &node
->entry
);
563 else list_add_tail( &parent
->children
, &node
->entry
);
564 reader
->current
= reader
->last
= node
;
567 static HRESULT
read_init_state( struct reader
*reader
)
571 destroy_nodes( reader
->root
);
573 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
574 reader
->nb_prefixes
= 1;
575 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
576 read_insert_eof( reader
, node
);
577 reader
->state
= READER_STATE_INITIAL
;
581 /**************************************************************************
582 * WsCreateReader [webservices.@]
584 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
585 WS_XML_READER
**handle
, WS_ERROR
*error
)
587 struct reader
*reader
;
588 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
589 WS_CHARSET charset
= WS_CHARSET_UTF8
;
590 BOOL read_decl
= TRUE
;
593 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
594 if (error
) FIXME( "ignoring error parameter\n" );
596 if (!handle
) return E_INVALIDARG
;
597 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
599 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
600 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
601 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
602 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
603 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
605 for (i
= 0; i
< count
; i
++)
607 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
608 properties
[i
].valueSize
);
611 free_reader( reader
);
616 if ((hr
= read_init_state( reader
)) != S_OK
)
618 free_reader( reader
);
622 *handle
= (WS_XML_READER
*)reader
;
626 /**************************************************************************
627 * WsFreeReader [webservices.@]
629 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
631 struct reader
*reader
= (struct reader
*)handle
;
633 TRACE( "%p\n", handle
);
634 free_reader( reader
);
637 /**************************************************************************
638 * WsFillReader [webservices.@]
640 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
643 struct reader
*reader
= (struct reader
*)handle
;
645 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
646 if (error
) FIXME( "ignoring error parameter\n" );
648 if (!reader
) return E_INVALIDARG
;
650 /* FIXME: add support for stream input */
651 reader
->read_size
= min( min_size
, reader
->input_size
);
652 reader
->read_pos
= 0;
657 /**************************************************************************
658 * WsGetErrorProperty [webservices.@]
660 HRESULT WINAPI
WsGetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, void *buf
,
663 struct error
*error
= (struct error
*)handle
;
665 TRACE( "%p %u %p %u\n", handle
, id
, buf
, size
);
666 return prop_get( error
->prop
, error
->prop_count
, id
, buf
, size
);
669 /**************************************************************************
670 * WsGetErrorString [webservices.@]
672 HRESULT WINAPI
WsGetErrorString( WS_ERROR
*handle
, ULONG index
, WS_STRING
*str
)
674 FIXME( "%p %u %p: stub\n", handle
, index
, str
);
678 /**************************************************************************
679 * WsGetHeapProperty [webservices.@]
681 HRESULT WINAPI
WsGetHeapProperty( WS_HEAP
*handle
, WS_HEAP_PROPERTY_ID id
, void *buf
,
682 ULONG size
, WS_ERROR
*error
)
684 struct heap
*heap
= (struct heap
*)handle
;
686 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
687 if (error
) FIXME( "ignoring error parameter\n" );
689 return prop_get( heap
->prop
, heap
->prop_count
, id
, buf
, size
);
692 /**************************************************************************
693 * WsGetNamespaceFromPrefix [webservices.@]
695 HRESULT WINAPI
WsGetNamespaceFromPrefix( WS_XML_READER
*handle
, const WS_XML_STRING
*prefix
,
696 BOOL required
, const WS_XML_STRING
**ns
, WS_ERROR
*error
)
698 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
699 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
700 static const WS_XML_STRING empty_ns
= {0, NULL
};
701 static const WS_XML_STRING xml_ns
= {36, (BYTE
*)"http://www.w3.org/XML/1998/namespace"};
702 static const WS_XML_STRING xmlns_ns
= {29, (BYTE
*)"http://www.w3.org/2000/xmlns/"};
703 struct reader
*reader
= (struct reader
*)handle
;
706 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(prefix
), required
, ns
, error
);
707 if (error
) FIXME( "ignoring error parameter\n" );
709 if (!reader
|| !prefix
|| !ns
) return E_INVALIDARG
;
710 if (reader
->state
!= READER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
717 else if (WsXmlStringEquals( prefix
, &xml
, NULL
) == S_OK
)
722 else if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
729 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
732 for (i
= 0; i
< elem
->attributeCount
; i
++)
734 if (!elem
->attributes
[i
]->isXmlNs
) continue;
735 if (WsXmlStringEquals( prefix
, elem
->attributes
[i
]->prefix
, NULL
) == S_OK
)
737 *ns
= elem
->attributes
[i
]->ns
;
746 if (required
) return WS_E_INVALID_FORMAT
;
753 /**************************************************************************
754 * WsGetReaderNode [webservices.@]
756 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
759 struct reader
*reader
= (struct reader
*)handle
;
761 TRACE( "%p %p %p\n", handle
, node
, error
);
762 if (error
) FIXME( "ignoring error parameter\n" );
764 if (!reader
|| !node
) return E_INVALIDARG
;
766 *node
= &reader
->current
->hdr
.node
;
770 /**************************************************************************
771 * WsGetReaderProperty [webservices.@]
773 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
774 void *buf
, ULONG size
, WS_ERROR
*error
)
776 struct reader
*reader
= (struct reader
*)handle
;
778 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
779 if (error
) FIXME( "ignoring error parameter\n" );
781 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
783 if (id
== WS_XML_READER_PROPERTY_CHARSET
)
788 if ((hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, &charset
, size
)) != S_OK
) return hr
;
789 if (!charset
) return WS_E_INVALID_FORMAT
;
790 *(WS_CHARSET
*)buf
= charset
;
793 return prop_get( reader
->prop
, reader
->prop_count
, id
, buf
, size
);
796 /**************************************************************************
797 * WsGetXmlAttribute [webservices.@]
799 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
800 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
802 FIXME( "%p %s %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
806 WS_XML_STRING
*alloc_xml_string( const unsigned char *data
, ULONG len
)
810 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
812 ret
->bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
813 ret
->dictionary
= NULL
;
815 if (data
) memcpy( ret
->bytes
, data
, len
);
819 WS_XML_UTF8_TEXT
*alloc_utf8_text( const unsigned char *data
, ULONG len
)
821 WS_XML_UTF8_TEXT
*ret
;
823 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
824 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
825 ret
->value
.length
= len
;
826 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
827 ret
->value
.dictionary
= NULL
;
829 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
833 static inline BOOL
read_end_of_data( struct reader
*reader
)
835 return reader
->read_pos
>= reader
->read_size
;
838 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
840 return &reader
->read_bufptr
[reader
->read_pos
];
843 /* UTF-8 support based on libs/wine/utf8.c */
845 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
846 static const char utf8_length
[128] =
848 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
849 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
850 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
851 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
852 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
853 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
854 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
855 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
858 /* first byte mask depending on UTF-8 sequence length */
859 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
861 /* minimum Unicode value depending on UTF-8 sequence length */
862 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
864 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
866 unsigned int len
, res
;
867 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
868 const unsigned char *end
;
870 if (reader
->read_pos
>= reader
->read_size
) return 0;
877 len
= utf8_length
[ch
- 0x80];
878 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
879 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
;
880 res
= ch
& utf8_mask
[len
];
885 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
886 res
= (res
<< 6) | ch
;
888 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
889 res
= (res
<< 6) | ch
;
891 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
892 res
= (res
<< 6) | ch
;
893 if (res
< utf8_minval
[len
]) break;
901 static inline void read_skip( struct reader
*reader
, unsigned int count
)
903 if (reader
->read_pos
+ count
> reader
->read_size
) return;
904 reader
->read_pos
+= count
;
907 static inline void read_rewind( struct reader
*reader
, unsigned int count
)
909 reader
->read_pos
-= count
;
912 static inline BOOL
read_isnamechar( unsigned int ch
)
914 /* FIXME: incomplete */
915 return (ch
>= 'A' && ch
<= 'Z') ||
916 (ch
>= 'a' && ch
<= 'z') ||
917 (ch
>= '0' && ch
<= '9') ||
918 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
921 static inline BOOL
read_isspace( unsigned int ch
)
923 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
926 static inline void read_skip_whitespace( struct reader
*reader
)
928 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
932 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
934 const unsigned char *ptr
= read_current_ptr( reader
);
936 if (len
< 0) len
= strlen( str
);
937 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
940 if (*str
!= *ptr
) return *ptr
- *str
;
946 static HRESULT
read_xmldecl( struct reader
*reader
)
948 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
950 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
952 reader
->state
= READER_STATE_BOF
;
955 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
956 read_skip( reader
, 6 );
958 /* FIXME: parse attributes */
959 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
962 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
963 read_skip( reader
, 2 );
965 reader
->state
= READER_STATE_BOF
;
969 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
971 if (elem
->attributeCount
)
973 WS_XML_ATTRIBUTE
**tmp
;
974 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
975 return E_OUTOFMEMORY
;
976 elem
->attributes
= tmp
;
978 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
979 elem
->attributes
[elem
->attributeCount
++] = attr
;
983 static HRESULT
parse_name( const unsigned char *str
, unsigned int len
,
984 WS_XML_STRING
**prefix
, WS_XML_STRING
**localname
)
986 const unsigned char *name_ptr
= str
, *prefix_ptr
= NULL
;
987 unsigned int i
, name_len
= len
, prefix_len
= 0;
989 for (i
= 0; i
< len
; i
++)
995 name_ptr
= &str
[i
+ 1];
1000 if (!(*prefix
= alloc_xml_string( prefix_ptr
, prefix_len
))) return E_OUTOFMEMORY
;
1001 if (!(*localname
= alloc_xml_string( name_ptr
, name_len
)))
1003 heap_free( *prefix
);
1004 return E_OUTOFMEMORY
;
1009 static HRESULT
read_attribute( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1011 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1012 WS_XML_ATTRIBUTE
*attr
;
1013 WS_XML_UTF8_TEXT
*text
;
1014 unsigned int len
= 0, ch
, skip
, quote
;
1015 const unsigned char *start
;
1016 WS_XML_STRING
*prefix
, *localname
;
1017 HRESULT hr
= WS_E_INVALID_FORMAT
;
1019 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1021 start
= read_current_ptr( reader
);
1024 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1025 if (!read_isnamechar( ch
)) break;
1026 read_skip( reader
, skip
);
1029 if (!len
) goto error
;
1031 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1033 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1035 heap_free( prefix
);
1037 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1039 heap_free( localname
);
1042 attr
->localName
= localname
;
1044 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1047 attr
->prefix
= prefix
;
1048 attr
->localName
= localname
;
1052 attr
->prefix
= prefix
;
1053 attr
->localName
= localname
;
1056 hr
= WS_E_INVALID_FORMAT
;
1057 read_skip_whitespace( reader
);
1058 if (read_cmp( reader
, "=", 1 )) goto error
;
1059 read_skip( reader
, 1 );
1061 read_skip_whitespace( reader
);
1062 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) goto error
;
1063 quote
= read_utf8_char( reader
, &skip
);
1064 read_skip( reader
, 1 );
1067 start
= read_current_ptr( reader
);
1070 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1071 if (ch
== quote
) break;
1072 read_skip( reader
, skip
);
1075 read_skip( reader
, 1 );
1080 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1081 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1082 if (!(text
= alloc_utf8_text( NULL
, 0 ))) goto error
;
1084 else if (!(text
= alloc_utf8_text( start
, len
))) goto error
;
1086 attr
->value
= &text
->text
;
1087 attr
->singleQuote
= (quote
== '\'');
1093 free_attribute( attr
);
1097 static inline BOOL
is_valid_parent( const struct node
*node
)
1099 if (!node
) return FALSE
;
1100 return node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
|| node_type( node
) == WS_XML_NODE_TYPE_BOF
;
1103 static struct node
*read_find_parent( struct reader
*reader
)
1105 struct node
*node
= reader
->current
;
1106 if (node_type( node
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1108 if (!node
->parent
|| !is_valid_parent( node
->parent
->parent
)) return NULL
;
1109 return node
->parent
->parent
;
1111 else if (is_valid_parent( node
)) return node
;
1112 else if (is_valid_parent( node
->parent
)) return node
->parent
;
1116 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1118 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1119 const WS_XML_STRING
*ns
;
1122 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1123 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1124 if (!elem
->ns
->length
) elem
->ns
->bytes
= (BYTE
*)(elem
->ns
+ 1); /* quirk */
1126 for (i
= 0; i
< elem
->attributeCount
; i
++)
1128 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1129 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1130 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1131 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1136 static HRESULT
read_element( struct reader
*reader
)
1138 unsigned int len
= 0, ch
, skip
;
1139 const unsigned char *start
;
1140 struct node
*node
= NULL
, *parent
;
1141 WS_XML_ELEMENT_NODE
*elem
;
1142 WS_XML_ATTRIBUTE
*attr
= NULL
;
1143 HRESULT hr
= WS_E_INVALID_FORMAT
;
1145 if (read_end_of_data( reader
))
1147 struct list
*eof
= list_tail( &reader
->root
->children
);
1148 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
1149 reader
->state
= READER_STATE_EOF
;
1153 if (read_cmp( reader
, "<", 1 )) goto error
;
1154 read_skip( reader
, 1 );
1155 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1157 read_rewind( reader
, 1 );
1161 start
= read_current_ptr( reader
);
1164 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1165 if (!read_isnamechar( ch
)) break;
1166 read_skip( reader
, skip
);
1169 if (!len
) goto error
;
1171 if (!(parent
= read_find_parent( reader
))) goto error
;
1174 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) goto error
;
1175 elem
= (WS_XML_ELEMENT_NODE
*)node
;
1176 if ((hr
= parse_name( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1178 reader
->current_attr
= 0;
1181 read_skip_whitespace( reader
);
1182 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1183 if ((hr
= read_attribute( reader
, &attr
)) != S_OK
) goto error
;
1184 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1186 free_attribute( attr
);
1189 reader
->current_attr
++;
1191 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1193 read_insert_node( reader
, parent
, node
);
1194 reader
->state
= READER_STATE_STARTELEMENT
;
1202 static HRESULT
read_text( struct reader
*reader
)
1204 unsigned int len
= 0, ch
, skip
;
1205 const unsigned char *start
;
1206 struct node
*node
, *parent
;
1207 WS_XML_TEXT_NODE
*text
;
1208 WS_XML_UTF8_TEXT
*utf8
;
1210 start
= read_current_ptr( reader
);
1213 if (read_end_of_data( reader
)) break;
1214 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1215 if (ch
== '<') break;
1216 read_skip( reader
, skip
);
1220 if (!(parent
= read_find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1222 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1223 text
= (WS_XML_TEXT_NODE
*)node
;
1224 if (!(utf8
= alloc_utf8_text( start
, len
)))
1227 return E_OUTOFMEMORY
;
1229 text
->text
= &utf8
->text
;
1231 read_insert_node( reader
, parent
, node
);
1232 reader
->state
= READER_STATE_TEXT
;
1236 static HRESULT
read_node( struct reader
* );
1238 static HRESULT
read_startelement( struct reader
*reader
)
1242 read_skip_whitespace( reader
);
1243 if (!read_cmp( reader
, "/>", 2 ))
1245 read_skip( reader
, 2 );
1246 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1247 read_insert_node( reader
, reader
->current
, node
);
1248 reader
->state
= READER_STATE_ENDELEMENT
;
1251 else if (!read_cmp( reader
, ">", 1 ))
1253 read_skip( reader
, 1 );
1254 return read_node( reader
);
1256 return WS_E_INVALID_FORMAT
;
1259 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
1263 switch (reader
->state
)
1265 case READER_STATE_INITIAL
:
1266 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
1269 case READER_STATE_STARTELEMENT
:
1270 if (found
) *found
= TRUE
;
1277 read_skip_whitespace( reader
);
1278 if ((hr
= read_element( reader
)) == S_OK
&& found
)
1280 if (reader
->state
== READER_STATE_STARTELEMENT
)
1289 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
1292 if (len1
!= len2
) return 1;
1293 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
1297 static struct node
*read_find_start_element( struct reader
*reader
, const WS_XML_STRING
*prefix
,
1298 const WS_XML_STRING
*localname
)
1300 struct node
*parent
;
1301 const WS_XML_STRING
*str
;
1303 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
1305 if (node_type( parent
) == WS_XML_NODE_TYPE_BOF
) return NULL
;
1306 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1308 str
= parent
->hdr
.prefix
;
1309 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
1310 str
= parent
->hdr
.localName
;
1311 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
1319 static HRESULT
read_endelement( struct reader
*reader
)
1321 struct node
*node
, *parent
;
1322 unsigned int len
= 0, ch
, skip
;
1323 const unsigned char *start
;
1324 WS_XML_STRING
*prefix
, *localname
;
1327 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
1329 if (read_end_of_data( reader
))
1331 struct list
*eof
= list_tail( &reader
->root
->children
);
1332 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
1333 reader
->state
= READER_STATE_EOF
;
1337 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
1338 read_skip( reader
, 2 );
1340 start
= read_current_ptr( reader
);
1343 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1346 read_skip( reader
, 1 );
1349 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
1350 read_skip( reader
, skip
);
1354 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
1355 parent
= read_find_start_element( reader
, prefix
, localname
);
1356 heap_free( prefix
);
1357 heap_free( localname
);
1358 if (!parent
) return WS_E_INVALID_FORMAT
;
1360 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1361 read_insert_node( reader
, parent
, node
);
1362 reader
->state
= READER_STATE_ENDELEMENT
;
1366 static HRESULT
read_comment( struct reader
*reader
)
1368 unsigned int len
= 0, ch
, skip
;
1369 const unsigned char *start
;
1370 struct node
*node
, *parent
;
1371 WS_XML_COMMENT_NODE
*comment
;
1373 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
1374 read_skip( reader
, 4 );
1376 start
= read_current_ptr( reader
);
1379 if (!read_cmp( reader
, "-->", 3 ))
1381 read_skip( reader
, 3 );
1384 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1385 read_skip( reader
, skip
);
1389 if (!(parent
= read_find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1391 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
1392 comment
= (WS_XML_COMMENT_NODE
*)node
;
1393 if (!(comment
->value
.bytes
= heap_alloc( len
)))
1396 return E_OUTOFMEMORY
;
1398 memcpy( comment
->value
.bytes
, start
, len
);
1399 comment
->value
.length
= len
;
1401 read_insert_node( reader
, parent
, node
);
1402 reader
->state
= READER_STATE_COMMENT
;
1406 static HRESULT
read_startcdata( struct reader
*reader
)
1408 struct node
*node
, *parent
;
1410 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
1411 read_skip( reader
, 9 );
1413 if (!(parent
= read_find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1415 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1416 read_insert_node( reader
, parent
, node
);
1417 reader
->state
= READER_STATE_STARTCDATA
;
1421 static HRESULT
read_cdata( struct reader
*reader
)
1423 unsigned int len
= 0, ch
, skip
;
1424 const unsigned char *start
;
1426 WS_XML_TEXT_NODE
*text
;
1427 WS_XML_UTF8_TEXT
*utf8
;
1429 start
= read_current_ptr( reader
);
1432 if (!read_cmp( reader
, "]]>", 3 )) break;
1433 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1434 read_skip( reader
, skip
);
1438 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1439 text
= (WS_XML_TEXT_NODE
*)node
;
1440 if (!(utf8
= alloc_utf8_text( start
, len
)))
1443 return E_OUTOFMEMORY
;
1445 text
->text
= &utf8
->text
;
1447 read_insert_node( reader
, reader
->current
, node
);
1448 reader
->state
= READER_STATE_CDATA
;
1452 static HRESULT
read_endcdata( struct reader
*reader
)
1456 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
1457 read_skip( reader
, 3 );
1459 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
1460 read_insert_node( reader
, reader
->current
->parent
, node
);
1461 reader
->state
= READER_STATE_ENDCDATA
;
1465 static HRESULT
read_node( struct reader
*reader
)
1471 if (read_end_of_data( reader
))
1473 struct list
*eof
= list_tail( &reader
->root
->children
);
1474 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
1475 reader
->state
= READER_STATE_EOF
;
1478 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
1479 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
1480 else if (!read_cmp( reader
, "<?", 2 ))
1482 hr
= read_xmldecl( reader
);
1483 if (FAILED( hr
)) return hr
;
1485 else if (!read_cmp( reader
, "</", 2 )) return read_endelement( reader
);
1486 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
1487 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment( reader
);
1488 else if (!read_cmp( reader
, "<", 1 )) return read_element( reader
);
1489 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement( reader
);
1490 else return read_text( reader
);
1494 /**************************************************************************
1495 * WsReadEndElement [webservices.@]
1497 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1499 struct reader
*reader
= (struct reader
*)handle
;
1501 TRACE( "%p %p\n", handle
, error
);
1502 if (error
) FIXME( "ignoring error parameter\n" );
1504 if (!reader
) return E_INVALIDARG
;
1505 return read_endelement( reader
);
1508 /**************************************************************************
1509 * WsReadNode [webservices.@]
1511 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
1513 struct reader
*reader
= (struct reader
*)handle
;
1515 TRACE( "%p %p\n", handle
, error
);
1516 if (error
) FIXME( "ignoring error parameter\n" );
1518 if (!reader
) return E_INVALIDARG
;
1519 return read_node( reader
);
1522 /**************************************************************************
1523 * WsReadStartElement [webservices.@]
1525 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1527 struct reader
*reader
= (struct reader
*)handle
;
1529 TRACE( "%p %p\n", handle
, error
);
1530 if (error
) FIXME( "ignoring error parameter\n" );
1532 if (!reader
) return E_INVALIDARG
;
1533 return read_startelement( reader
);
1536 /**************************************************************************
1537 * WsReadToStartElement [webservices.@]
1539 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
1540 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
1542 struct reader
*reader
= (struct reader
*)handle
;
1544 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
1545 if (error
) FIXME( "ignoring error parameter\n" );
1547 if (!reader
) return E_INVALIDARG
;
1548 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
1550 return read_to_startelement( reader
, found
);
1553 static BOOL
move_to_root_element( struct reader
*reader
)
1558 if (!(ptr
= list_head( &reader
->root
->children
))) return FALSE
;
1559 node
= LIST_ENTRY( ptr
, struct node
, entry
);
1560 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
1562 reader
->current
= node
;
1565 while ((ptr
= list_next( &reader
->root
->children
, &node
->entry
)))
1567 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1568 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1570 reader
->current
= next
;
1578 static BOOL
move_to_next_element( struct reader
*reader
)
1581 struct node
*node
= reader
->current
;
1583 while ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
1585 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1586 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1588 reader
->current
= next
;
1596 static BOOL
move_to_prev_element( struct reader
*reader
)
1599 struct node
*node
= reader
->current
;
1601 while ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
1603 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
1604 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
1606 reader
->current
= prev
;
1614 static BOOL
move_to_child_element( struct reader
*reader
)
1619 if (!(ptr
= list_head( &reader
->current
->children
))) return FALSE
;
1620 node
= LIST_ENTRY( ptr
, struct node
, entry
);
1621 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
1623 reader
->current
= node
;
1626 while ((ptr
= list_next( &reader
->current
->children
, &node
->entry
)))
1628 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1629 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1631 reader
->current
= next
;
1639 static BOOL
move_to_end_element( struct reader
*reader
)
1642 struct node
*node
= reader
->current
;
1644 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
1646 if ((ptr
= list_tail( &node
->children
)))
1648 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
1649 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1651 reader
->current
= tail
;
1658 static BOOL
move_to_parent_element( struct reader
*reader
)
1660 struct node
*parent
= reader
->current
->parent
;
1662 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
1663 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
1665 reader
->current
= parent
;
1671 static BOOL
move_to_first_node( struct reader
*reader
)
1674 if ((ptr
= list_head( &reader
->current
->parent
->children
)))
1676 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1682 static BOOL
move_to_next_node( struct reader
*reader
)
1685 if ((ptr
= list_next( &reader
->current
->parent
->children
, &reader
->current
->entry
)))
1687 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1693 static BOOL
move_to_prev_node( struct reader
*reader
)
1696 if ((ptr
= list_prev( &reader
->current
->parent
->children
, &reader
->current
->entry
)))
1698 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1704 static BOOL
move_to_child_node( struct reader
*reader
)
1707 if ((ptr
= list_head( &reader
->current
->children
)))
1709 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1715 static BOOL
move_to_parent_node( struct reader
*reader
)
1717 struct node
*parent
= reader
->current
->parent
;
1718 if (!parent
) return FALSE
;
1719 reader
->current
= parent
;
1723 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
1726 BOOL success
= FALSE
;
1729 if (!read_end_of_data( reader
))
1731 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
1732 if (hr
!= S_OK
) return hr
;
1736 case WS_MOVE_TO_ROOT_ELEMENT
:
1737 success
= move_to_root_element( reader
);
1740 case WS_MOVE_TO_NEXT_ELEMENT
:
1741 success
= move_to_next_element( reader
);
1744 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
1745 success
= move_to_prev_element( reader
);
1748 case WS_MOVE_TO_CHILD_ELEMENT
:
1749 success
= move_to_child_element( reader
);
1752 case WS_MOVE_TO_END_ELEMENT
:
1753 success
= move_to_end_element( reader
);
1756 case WS_MOVE_TO_PARENT_ELEMENT
:
1757 success
= move_to_parent_element( reader
);
1760 case WS_MOVE_TO_FIRST_NODE
:
1761 success
= move_to_first_node( reader
);
1764 case WS_MOVE_TO_NEXT_NODE
:
1765 success
= move_to_next_node( reader
);
1768 case WS_MOVE_TO_PREVIOUS_NODE
:
1769 success
= move_to_prev_node( reader
);
1772 case WS_MOVE_TO_CHILD_NODE
:
1773 success
= move_to_child_node( reader
);
1776 case WS_MOVE_TO_BOF
:
1777 reader
->current
= reader
->root
;
1781 case WS_MOVE_TO_EOF
:
1782 if ((ptr
= list_tail( &reader
->root
->children
)))
1784 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1790 FIXME( "unhandled move %u\n", move
);
1799 return success
? S_OK
: WS_E_INVALID_FORMAT
;
1802 /**************************************************************************
1803 * WsMoveReader [webservices.@]
1805 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
1807 struct reader
*reader
= (struct reader
*)handle
;
1809 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
1810 if (error
) FIXME( "ignoring error parameter\n" );
1812 if (!reader
) return E_INVALIDARG
;
1813 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
1815 return read_move_to( reader
, move
, found
);
1818 /**************************************************************************
1819 * WsReadStartAttribute [webservices.@]
1821 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
1823 struct reader
*reader
= (struct reader
*)handle
;
1824 WS_XML_ELEMENT_NODE
*elem
;
1826 TRACE( "%p %u %p\n", handle
, index
, error
);
1827 if (error
) FIXME( "ignoring error parameter\n" );
1829 if (!reader
) return E_INVALIDARG
;
1831 elem
= &reader
->current
->hdr
;
1832 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
1833 return WS_E_INVALID_FORMAT
;
1835 reader
->current_attr
= index
;
1836 reader
->state
= READER_STATE_STARTATTRIBUTE
;
1840 /**************************************************************************
1841 * WsReadEndAttribute [webservices.@]
1843 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
1845 struct reader
*reader
= (struct reader
*)handle
;
1847 TRACE( "%p %p\n", handle
, error
);
1848 if (error
) FIXME( "ignoring error parameter\n" );
1850 if (!reader
) return E_INVALIDARG
;
1852 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
1853 return WS_E_INVALID_FORMAT
;
1855 reader
->state
= READER_STATE_STARTELEMENT
;
1859 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
1863 switch (text
->textType
)
1865 case WS_XML_TEXT_TYPE_UTF8
:
1867 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1868 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
1869 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
1870 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
1875 FIXME( "unhandled type %u\n", text
->textType
);
1882 #define MAX_INT8 0x7f
1883 #define MIN_INT8 (-MAX_INT8 - 1)
1884 #define MAX_INT16 0x7fff
1885 #define MIN_INT16 (-MAX_INT16 - 1)
1886 #define MAX_INT32 0x7fffffff
1887 #define MIN_INT32 (-MAX_INT32 - 1)
1888 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1889 #define MIN_INT64 (-MAX_INT64 - 1)
1890 #define MAX_UINT8 0xff
1891 #define MAX_UINT16 0xffff
1892 #define MAX_UINT32 0xffffffff
1893 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1895 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
1897 BOOL negative
= FALSE
;
1898 const unsigned char *ptr
= str
;
1901 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
1902 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
1903 if (!len
) return WS_E_INVALID_FORMAT
;
1911 if (!len
) return WS_E_INVALID_FORMAT
;
1917 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
1919 if (negative
) val
= -val
;
1921 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
1922 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
1924 return WS_E_NUMERIC_OVERFLOW
;
1926 *ret
= *ret
* 10 + val
;
1933 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
1935 const unsigned char *ptr
= str
;
1938 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
1939 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
1940 if (!len
) return WS_E_INVALID_FORMAT
;
1946 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
1949 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
1950 *ret
= *ret
* 10 + val
;
1957 #if defined(__i386__) || defined(__x86_64__)
1959 #define RC_DOWN 0x100;
1960 static BOOL
set_fp_rounding( unsigned short *save
)
1963 unsigned short fpword
;
1965 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
1968 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
1971 FIXME( "not implemented\n" );
1975 static void restore_fp_rounding( unsigned short fpword
)
1978 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
1980 FIXME( "not implemented\n" );
1984 static BOOL
set_fp_rounding( unsigned short *save
)
1986 FIXME( "not implemented\n" );
1989 static void restore_fp_rounding( unsigned short fpword
)
1991 FIXME( "not implemented\n" );
1995 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
1997 static const unsigned __int64 nan
= 0xfff8000000000000;
1998 static const unsigned __int64 inf
= 0x7ff0000000000000;
1999 static const unsigned __int64 inf_min
= 0xfff0000000000000;
2000 HRESULT hr
= WS_E_INVALID_FORMAT
;
2001 const unsigned char *p
= str
, *q
;
2002 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
2003 unsigned __int64 val
= 0, tmp
;
2004 long double exp_val
= 1.0, exp_mul
= 10.0;
2005 unsigned short fpword
;
2007 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2008 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2009 if (!len
) return WS_E_INVALID_FORMAT
;
2011 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
2013 *(unsigned __int64
*)ret
= nan
;
2016 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
2018 *(unsigned __int64
*)ret
= inf
;
2021 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
2023 *(unsigned __int64
*)ret
= inf_min
;
2033 else if (*p
== '+') { p
++; len
--; };
2034 if (!len
) return S_OK
;
2036 if (!set_fp_rounding( &fpword
)) return E_NOTIMPL
;
2039 while (len
&& isdigit( *q
)) { q
++; len
--; }
2040 have_digits
= nb_digits
= q
- p
;
2041 for (i
= 0; i
< nb_digits
; i
++)
2043 tmp
= val
* 10 + p
[i
] - '0';
2044 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
2046 for (; i
< nb_digits
; i
++) exp
++;
2057 while (len
&& isdigit( *q
)) { q
++; len
--; };
2058 have_digits
|= nb_digits
= q
- p
;
2059 for (i
= 0; i
< nb_digits
; i
++)
2061 tmp
= val
* 10 + p
[i
] - '0';
2062 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
2067 if (len
> 1 && tolower(*q
) == 'e')
2069 if (!have_digits
) goto done
;
2076 else if (*p
== '+') { p
++; len
--; };
2079 while (len
&& isdigit( *q
)) { q
++; len
--; };
2081 if (!nb_digits
|| len
) goto done
;
2082 for (i
= 0; i
< nb_digits
; i
++)
2084 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
2085 exp_tmp
= MAX_INT32
;
2087 exp_tmp
*= exp_sign
;
2089 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
2090 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
2091 else exp
+= exp_tmp
;
2094 if (!have_digits
|| len
) goto done
;
2096 if ((neg_exp
= exp
< 0)) exp
= -exp
;
2097 for (; exp
; exp
>>= 1)
2099 if (exp
& 1) exp_val
*= exp_mul
;
2103 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
2107 restore_fp_rounding( fpword
);
2111 static HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
2113 static const unsigned char hex
[] =
2115 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
2116 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
2117 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
2118 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
2119 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
2120 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
2121 0,10,11,12,13,14,15 /* 0x60 */
2123 const unsigned char *p
= str
;
2126 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2127 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2128 if (len
!= 36) return WS_E_INVALID_FORMAT
;
2130 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
2131 return WS_E_INVALID_FORMAT
;
2133 for (i
= 0; i
< 36; i
++)
2135 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
2136 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
2139 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
2140 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
2142 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
2143 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
2145 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
2146 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
2147 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
2148 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
2149 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
2150 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
2151 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
2152 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
2157 #define TICKS_PER_SEC 10000000
2158 #define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
2159 #define TICKS_PER_HOUR (3600 * (ULONGLONG)TICKS_PER_SEC)
2160 #define TICKS_PER_DAY (86400 * (ULONGLONG)TICKS_PER_SEC)
2161 #define TICKS_MAX 3155378975999999999
2163 static const int month_offsets
[2][12] =
2165 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
2166 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
2169 static const int month_days
[2][12] =
2171 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
2172 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
2175 static inline int is_leap_year( int year
)
2177 return !(year
% 4) && (year
% 100 || !(year
% 400));
2180 static inline int valid_day( int year
, int month
, int day
)
2182 return day
> 0 && day
<= month_days
[is_leap_year( year
)][month
- 1];
2185 static inline int leap_days_before( int year
)
2187 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
2190 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
2192 const unsigned char *p
= bytes
, *q
;
2193 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
2195 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2196 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2199 while (len
&& isdigit( *q
)) { q
++; len
--; };
2200 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2201 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
2202 if (year
< 1) return WS_E_INVALID_FORMAT
;
2205 while (len
&& isdigit( *q
)) { q
++; len
--; };
2206 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2207 month
= (p
[0] - '0') * 10 + p
[1] - '0';
2208 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
2211 while (len
&& isdigit( *q
)) { q
++; len
--; };
2212 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
2213 day
= (p
[0] - '0') * 10 + p
[1] - '0';
2214 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
2217 while (len
&& isdigit( *q
)) { q
++; len
--; };
2218 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2219 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2220 if (hour
> 24) return WS_E_INVALID_FORMAT
;
2223 while (len
&& isdigit( *q
)) { q
++; len
--; };
2224 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2225 min
= (p
[0] - '0') * 10 + p
[1] - '0';
2226 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2229 while (len
&& isdigit( *q
)) { q
++; len
--; };
2230 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
2231 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
2232 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2236 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
2238 while (len
&& isdigit( *q
)) { q
++; len
--; };
2240 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
2241 for (i
= 0; i
< nb_digits
; i
++)
2243 sec_frac
+= (p
[i
] - '0') * mul
;
2249 if (--len
) return WS_E_INVALID_FORMAT
;
2250 tz_hour
= tz_min
= tz_neg
= 0;
2251 ret
->format
= WS_DATETIME_FORMAT_UTC
;
2253 else if (*q
== '+' || *q
== '-')
2255 tz_neg
= (*q
== '-') ? 1 : 0;
2258 while (len
&& isdigit( *q
)) { q
++; len
--; };
2259 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2260 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2261 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
2264 while (len
&& isdigit( *q
)) { q
++; len
--; };
2265 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
2266 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
2267 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
2269 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
2271 else return WS_E_INVALID_FORMAT
;
2273 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
2274 ret
->ticks
+= month_offsets
[is_leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
2275 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
2276 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
2277 ret
->ticks
+= min
* TICKS_PER_MIN
;
2278 ret
->ticks
+= sec
* TICKS_PER_SEC
;
2279 ret
->ticks
+= sec_frac
;
2283 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
2284 return WS_E_INVALID_FORMAT
;
2285 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
2286 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
2290 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
2291 return WS_E_INVALID_FORMAT
;
2292 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
2293 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
2299 #define TICKS_1601_01_01 504911232000000000
2301 /**************************************************************************
2302 * WsDateTimeToFileTime [webservices.@]
2304 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
2306 unsigned __int64 ticks
;
2308 TRACE( "%p %p %p\n", dt
, ft
, error
);
2309 if (error
) FIXME( "ignoring error parameter\n" );
2311 if (!dt
|| !ft
) return E_INVALIDARG
;
2313 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
2314 ticks
= dt
->ticks
- TICKS_1601_01_01
;
2315 ft
->dwHighDateTime
= ticks
>> 32;
2316 ft
->dwLowDateTime
= (DWORD
)ticks
;
2320 /**************************************************************************
2321 * WsFileTimeToDateTime [webservices.@]
2323 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
2325 unsigned __int64 ticks
;
2327 TRACE( "%p %p %p\n", ft
, dt
, error
);
2328 if (error
) FIXME( "ignoring error parameter\n" );
2330 if (!dt
|| !ft
) return E_INVALIDARG
;
2332 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
2333 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
2334 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
2335 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
2336 dt
->format
= WS_DATETIME_FORMAT_UTC
;
2340 static HRESULT
read_get_node_text( struct reader
*reader
, WS_XML_UTF8_TEXT
**ret
)
2342 WS_XML_TEXT_NODE
*text
;
2344 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
2345 return WS_E_INVALID_FORMAT
;
2347 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
2348 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2350 FIXME( "text type %u not supported\n", text
->text
->textType
);
2353 *ret
= (WS_XML_UTF8_TEXT
*)text
->text
;
2357 static HRESULT
read_get_attribute_text( struct reader
*reader
, ULONG index
, WS_XML_UTF8_TEXT
**ret
)
2359 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2360 WS_XML_ATTRIBUTE
*attr
;
2362 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2363 return WS_E_INVALID_FORMAT
;
2365 attr
= elem
->attributes
[index
];
2366 if (attr
->value
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2368 FIXME( "text type %u not supported\n", attr
->value
->textType
);
2371 *ret
= (WS_XML_UTF8_TEXT
*)attr
->value
;
2375 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
2376 const WS_XML_STRING
*ns
, ULONG
*index
)
2379 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2383 *index
= reader
->current_attr
;
2386 for (i
= 0; i
< elem
->attributeCount
; i
++)
2388 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
2389 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
2391 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
2392 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
2401 /**************************************************************************
2402 * WsFindAttribute [webservices.@]
2404 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2405 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
2408 struct reader
*reader
= (struct reader
*)handle
;
2410 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
2411 required
, index
, error
);
2412 if (error
) FIXME( "ignoring error parameter\n" );
2414 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
2416 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2417 return WS_E_INVALID_OPERATION
;
2419 if (!find_attribute( reader
, localname
, ns
, index
))
2421 if (required
) return WS_E_INVALID_FORMAT
;
2428 static HRESULT
read_get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2429 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2430 WS_XML_UTF8_TEXT
**ret
, BOOL
*found
)
2434 case WS_ATTRIBUTE_TYPE_MAPPING
:
2437 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
2438 return read_get_attribute_text( reader
, index
, ret
);
2440 case WS_ELEMENT_TYPE_MAPPING
:
2441 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2442 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2448 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2450 if (WsXmlStringEquals( localname
, elem
->localName
, NULL
) != S_OK
||
2451 WsXmlStringEquals( ns
, elem
->ns
, NULL
) != S_OK
)
2456 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
2458 return read_get_node_text( reader
, ret
);
2461 FIXME( "mapping %u not supported\n", mapping
);
2466 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2467 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2468 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2469 WS_HEAP
*heap
, void *ret
, ULONG size
)
2471 WS_XML_UTF8_TEXT
*utf8
;
2473 BOOL found
, val
= FALSE
;
2477 FIXME( "description not supported\n" );
2480 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2483 ULONG len
= utf8
->value
.length
;
2484 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
2485 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
2486 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
2487 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
2488 else return WS_E_INVALID_FORMAT
;
2493 case WS_READ_REQUIRED_VALUE
:
2494 if (!found
) return WS_E_INVALID_FORMAT
;
2495 if (size
!= sizeof(BOOL
)) return E_INVALIDARG
;
2499 case WS_READ_REQUIRED_POINTER
:
2500 if (!found
) return WS_E_INVALID_FORMAT
;
2503 case WS_READ_OPTIONAL_POINTER
:
2505 BOOL
*heap_val
= NULL
;
2506 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2509 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2512 *(BOOL
**)ret
= heap_val
;
2516 FIXME( "read option %u not supported\n", option
);
2523 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2524 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2525 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2526 WS_HEAP
*heap
, void *ret
, ULONG size
)
2528 WS_XML_UTF8_TEXT
*utf8
;
2535 FIXME( "description not supported\n" );
2538 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2539 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
2544 case WS_READ_REQUIRED_VALUE
:
2545 if (!found
) return WS_E_INVALID_FORMAT
;
2546 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
2550 case WS_READ_REQUIRED_POINTER
:
2551 if (!found
) return WS_E_INVALID_FORMAT
;
2554 case WS_READ_OPTIONAL_POINTER
:
2556 INT8
*heap_val
= NULL
;
2557 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2560 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2563 *(INT8
**)ret
= heap_val
;
2567 FIXME( "read option %u not supported\n", option
);
2574 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2575 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2576 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2577 WS_HEAP
*heap
, void *ret
, ULONG size
)
2579 WS_XML_UTF8_TEXT
*utf8
;
2586 FIXME( "description not supported\n" );
2589 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2590 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
2595 case WS_READ_REQUIRED_VALUE
:
2596 if (!found
) return WS_E_INVALID_FORMAT
;
2597 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
2598 *(INT16
*)ret
= val
;
2601 case WS_READ_REQUIRED_POINTER
:
2602 if (!found
) return WS_E_INVALID_FORMAT
;
2605 case WS_READ_OPTIONAL_POINTER
:
2607 INT16
*heap_val
= NULL
;
2608 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2611 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2614 *(INT16
**)ret
= heap_val
;
2618 FIXME( "read option %u not supported\n", option
);
2625 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2626 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2627 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2628 WS_HEAP
*heap
, void *ret
, ULONG size
)
2630 WS_XML_UTF8_TEXT
*utf8
;
2637 FIXME( "description not supported\n" );
2640 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2641 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
2646 case WS_READ_REQUIRED_VALUE
:
2647 if (!found
) return WS_E_INVALID_FORMAT
;
2648 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
2649 *(INT32
*)ret
= val
;
2652 case WS_READ_REQUIRED_POINTER
:
2653 if (!found
) return WS_E_INVALID_FORMAT
;
2656 case WS_READ_OPTIONAL_POINTER
:
2658 INT32
*heap_val
= NULL
;
2659 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2662 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2665 *(INT32
**)ret
= heap_val
;
2669 FIXME( "read option %u not supported\n", option
);
2676 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2677 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2678 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2679 WS_HEAP
*heap
, void *ret
, ULONG size
)
2681 WS_XML_UTF8_TEXT
*utf8
;
2688 FIXME( "description not supported\n" );
2691 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2692 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
2697 case WS_READ_REQUIRED_VALUE
:
2698 if (!found
) return WS_E_INVALID_FORMAT
;
2699 if (size
!= sizeof(INT64
)) return E_INVALIDARG
;
2700 *(INT64
*)ret
= val
;
2703 case WS_READ_REQUIRED_POINTER
:
2704 if (!found
) return WS_E_INVALID_FORMAT
;
2707 case WS_READ_OPTIONAL_POINTER
:
2709 INT64
*heap_val
= NULL
;
2710 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2713 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2716 *(INT64
**)ret
= heap_val
;
2720 FIXME( "read option %u not supported\n", option
);
2727 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2728 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2729 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2730 WS_HEAP
*heap
, void *ret
, ULONG size
)
2732 WS_XML_UTF8_TEXT
*utf8
;
2739 FIXME( "description not supported\n" );
2742 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2743 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
2748 case WS_READ_REQUIRED_VALUE
:
2749 if (!found
) return WS_E_INVALID_FORMAT
;
2750 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
2751 *(UINT8
*)ret
= val
;
2754 case WS_READ_REQUIRED_POINTER
:
2755 if (!found
) return WS_E_INVALID_FORMAT
;
2758 case WS_READ_OPTIONAL_POINTER
:
2760 UINT8
*heap_val
= NULL
;
2761 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2764 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2767 *(UINT8
**)ret
= heap_val
;
2771 FIXME( "read option %u not supported\n", option
);
2778 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2779 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2780 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2781 WS_HEAP
*heap
, void *ret
, ULONG size
)
2783 WS_XML_UTF8_TEXT
*utf8
;
2790 FIXME( "description not supported\n" );
2793 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2794 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
2799 case WS_READ_REQUIRED_VALUE
:
2800 if (!found
) return WS_E_INVALID_FORMAT
;
2801 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
2802 *(UINT16
*)ret
= val
;
2805 case WS_READ_REQUIRED_POINTER
:
2806 if (!found
) return WS_E_INVALID_FORMAT
;
2809 case WS_READ_OPTIONAL_POINTER
:
2811 UINT16
*heap_val
= NULL
;
2812 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2815 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2818 *(UINT16
**)ret
= heap_val
;
2822 FIXME( "read option %u not supported\n", option
);
2829 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2830 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2831 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2832 WS_HEAP
*heap
, void *ret
, ULONG size
)
2834 WS_XML_UTF8_TEXT
*utf8
;
2841 FIXME( "description not supported\n" );
2844 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2845 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
2850 case WS_READ_REQUIRED_VALUE
:
2851 if (!found
) return WS_E_INVALID_FORMAT
;
2852 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
2853 *(UINT32
*)ret
= val
;
2856 case WS_READ_REQUIRED_POINTER
:
2857 if (!found
) return WS_E_INVALID_FORMAT
;
2860 case WS_READ_OPTIONAL_POINTER
:
2862 UINT32
*heap_val
= NULL
;
2863 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2866 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2869 *(UINT32
**)ret
= heap_val
;
2873 FIXME( "read option %u not supported\n", option
);
2880 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2881 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2882 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2883 WS_HEAP
*heap
, void *ret
, ULONG size
)
2885 WS_XML_UTF8_TEXT
*utf8
;
2892 FIXME( "description not supported\n" );
2895 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2896 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
)) != S_OK
)
2901 case WS_READ_REQUIRED_VALUE
:
2902 if (!found
) return WS_E_INVALID_FORMAT
;
2903 if (size
!= sizeof(UINT64
)) return E_INVALIDARG
;
2904 *(UINT64
*)ret
= val
;
2907 case WS_READ_REQUIRED_POINTER
:
2908 if (!found
) return WS_E_INVALID_FORMAT
;
2911 case WS_READ_OPTIONAL_POINTER
:
2913 UINT64
*heap_val
= NULL
;
2914 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2917 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2920 *(UINT64
**)ret
= heap_val
;
2924 FIXME( "read option %u not supported\n", option
);
2931 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2932 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2933 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2934 WS_HEAP
*heap
, void *ret
, ULONG size
)
2936 WS_XML_UTF8_TEXT
*utf8
;
2941 if (desc
) FIXME( "ignoring description\n" );
2943 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2944 if (found
&& (hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
2948 case WS_READ_REQUIRED_VALUE
:
2949 if (!found
) return WS_E_INVALID_FORMAT
;
2950 if (size
!= sizeof(double)) return E_INVALIDARG
;
2951 *(double *)ret
= val
;
2954 case WS_READ_REQUIRED_POINTER
:
2955 if (!found
) return WS_E_INVALID_FORMAT
;
2958 case WS_READ_OPTIONAL_POINTER
:
2960 double *heap_val
= NULL
;
2961 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2964 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2967 *(double **)ret
= heap_val
;
2971 FIXME( "read option %u not supported\n", option
);
2978 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2979 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2980 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2981 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
2983 WS_XML_UTF8_TEXT
*utf8
;
2990 FIXME( "description not supported\n" );
2993 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2994 if (found
&& !(str
= xmltext_to_widechar( heap
, &utf8
->text
))) return WS_E_QUOTA_EXCEEDED
;
2998 case WS_READ_REQUIRED_POINTER
:
2999 if (!found
) return WS_E_INVALID_FORMAT
;
3002 case WS_READ_OPTIONAL_POINTER
:
3003 if (size
!= sizeof(str
)) return E_INVALIDARG
;
3008 FIXME( "read option %u not supported\n", option
);
3015 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
3018 for (i
= 0; i
< desc
->valueCount
; i
++)
3020 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
3022 *ret
= desc
->values
[i
].value
;
3026 return WS_E_INVALID_FORMAT
;
3029 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3030 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3031 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3032 WS_HEAP
*heap
, void *ret
, ULONG size
)
3034 WS_XML_UTF8_TEXT
*utf8
;
3039 if (!desc
) return E_INVALIDARG
;
3041 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3042 if (found
&& (hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
3046 case WS_READ_REQUIRED_VALUE
:
3047 if (!found
) return WS_E_INVALID_FORMAT
;
3048 if (size
!= sizeof(int)) return E_INVALIDARG
;
3052 case WS_READ_REQUIRED_POINTER
:
3053 if (!found
) return WS_E_INVALID_FORMAT
;
3056 case WS_READ_OPTIONAL_POINTER
:
3058 int *heap_val
= NULL
;
3059 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3062 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3065 *(int **)ret
= heap_val
;
3069 FIXME( "read option %u not supported\n", option
);
3076 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3077 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3078 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3079 WS_HEAP
*heap
, void *ret
, ULONG size
)
3081 WS_XML_UTF8_TEXT
*utf8
;
3083 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
3086 if (desc
) FIXME( "ignoring description\n" );
3088 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3089 if (found
&& (hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3093 case WS_READ_REQUIRED_VALUE
:
3094 if (!found
) return WS_E_INVALID_FORMAT
;
3095 if (size
!= sizeof(WS_DATETIME
)) return E_INVALIDARG
;
3096 *(WS_DATETIME
*)ret
= val
;
3099 case WS_READ_REQUIRED_POINTER
:
3100 if (!found
) return WS_E_INVALID_FORMAT
;
3103 case WS_READ_OPTIONAL_POINTER
:
3105 WS_DATETIME
*heap_val
= NULL
;
3106 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3109 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3112 *(WS_DATETIME
**)ret
= heap_val
;
3116 FIXME( "read option %u not supported\n", option
);
3123 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3124 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3125 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3126 WS_HEAP
*heap
, void *ret
, ULONG size
)
3128 WS_XML_UTF8_TEXT
*utf8
;
3133 if (desc
) FIXME( "ignoring description\n" );
3135 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3136 if (found
&& (hr
= str_to_guid( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3140 case WS_READ_REQUIRED_VALUE
:
3141 if (!found
) return WS_E_INVALID_FORMAT
;
3142 if (size
!= sizeof(GUID
)) return E_INVALIDARG
;
3146 case WS_READ_REQUIRED_POINTER
:
3147 if (!found
) return WS_E_INVALID_FORMAT
;
3150 case WS_READ_OPTIONAL_POINTER
:
3152 GUID
*heap_val
= NULL
;
3153 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3156 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3159 *(GUID
**)ret
= heap_val
;
3163 FIXME( "read option %u not supported\n", option
);
3170 static BOOL
is_empty_text_node( const struct node
*node
)
3172 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
3173 const WS_XML_UTF8_TEXT
*utf8
;
3176 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
3177 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3179 ERR( "unhandled text type %u\n", text
->text
->textType
);
3182 utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
3183 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
3187 static HRESULT
read_next_node( struct reader
*reader
)
3189 if (reader
->current
== reader
->last
) return read_node( reader
);
3190 if (move_to_child_node( reader
)) return S_OK
;
3191 if (move_to_next_node( reader
)) return S_OK
;
3192 if (!move_to_parent_node( reader
)) return WS_E_INVALID_FORMAT
;
3193 if (move_to_next_node( reader
)) return S_OK
;
3194 return WS_E_INVALID_FORMAT
;
3197 /* skips comment and empty text nodes */
3198 static HRESULT
read_type_next_node( struct reader
*reader
)
3203 WS_XML_NODE_TYPE type
;
3205 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3206 type
= node_type( reader
->current
);
3207 if (type
== WS_XML_NODE_TYPE_COMMENT
||
3208 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
3213 static BOOL
match_current_element( struct reader
*reader
, const WS_XML_STRING
*localname
,
3214 const WS_XML_STRING
*ns
)
3216 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3217 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
3218 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
3219 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
3222 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
3223 const WS_XML_STRING
*ns
)
3229 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
3230 if (reader
->current
== reader
->last
)
3233 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
3234 if (!found
) return WS_E_INVALID_FORMAT
;
3236 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3238 node
= reader
->current
;
3239 attr
= reader
->current_attr
;
3241 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
3242 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3244 reader
->current
= node
;
3245 reader
->current_attr
= attr
;
3247 return WS_E_INVALID_FORMAT
;
3250 static ULONG
get_type_size( WS_TYPE type
, const WS_STRUCT_DESCRIPTION
*desc
)
3256 return sizeof(INT8
);
3259 case WS_UINT16_TYPE
:
3260 return sizeof(INT16
);
3264 case WS_UINT32_TYPE
:
3266 return sizeof(INT32
);
3269 case WS_UINT64_TYPE
:
3270 return sizeof(INT64
);
3272 case WS_DOUBLE_TYPE
:
3273 return sizeof(double);
3275 case WS_DATETIME_TYPE
:
3276 return sizeof(WS_DATETIME
);
3279 return sizeof(GUID
);
3282 return sizeof(WCHAR
*);
3284 case WS_STRUCT_TYPE
:
3288 ERR( "unhandled type %u\n", type
);
3293 static WS_READ_OPTION
get_array_read_option( WS_TYPE type
)
3303 case WS_UINT16_TYPE
:
3304 case WS_UINT32_TYPE
:
3305 case WS_UINT64_TYPE
:
3306 case WS_DOUBLE_TYPE
:
3308 case WS_STRUCT_TYPE
:
3309 case WS_DATETIME_TYPE
:
3311 return WS_READ_REQUIRED_VALUE
;
3314 return WS_READ_REQUIRED_POINTER
;
3317 FIXME( "unhandled type %u\n", type
);
3322 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
3323 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
3326 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3327 WS_HEAP
*heap
, void **ret
, ULONG size
, ULONG
*count
)
3330 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
3331 WS_READ_OPTION option
;
3334 if (size
!= sizeof(void *) || !(option
= get_array_read_option( desc
->type
))) return E_INVALIDARG
;
3336 /* wrapper element */
3337 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
3340 if (option
== WS_READ_REQUIRED_VALUE
)
3341 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
3343 item_size
= sizeof(void *);
3345 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
3348 if (nb_items
>= nb_allocated
)
3350 if (!(buf
= ws_realloc_zero( heap
, buf
, nb_allocated
* 2 * item_size
)))
3351 return WS_E_QUOTA_EXCEEDED
;
3354 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
3355 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
3356 if (hr
== WS_E_INVALID_FORMAT
) break;
3359 ws_free( heap
, buf
);
3362 offset
+= item_size
;
3366 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
3368 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
3370 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
3371 desc
->itemRange
->maxItemCount
);
3372 ws_free( heap
, buf
);
3373 return WS_E_INVALID_FORMAT
;
3382 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3383 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
3386 if (reader
->current
== reader
->last
)
3389 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
3390 if (!found
) return WS_E_INVALID_FORMAT
;
3392 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3393 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
3395 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
3396 desc
->typeDescription
, option
, heap
, ret
, size
);
3399 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
)
3409 case WS_UINT16_TYPE
:
3410 case WS_UINT32_TYPE
:
3411 case WS_UINT64_TYPE
:
3412 case WS_DOUBLE_TYPE
:
3414 case WS_DATETIME_TYPE
:
3416 return WS_READ_REQUIRED_VALUE
;
3419 case WS_STRUCT_TYPE
:
3420 return WS_READ_REQUIRED_POINTER
;
3423 FIXME( "unhandled type %u\n", type
);
3428 static HRESULT
read_type_struct_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3429 WS_HEAP
*heap
, char *buf
)
3432 WS_READ_OPTION option
;
3436 if (!desc
) return E_INVALIDARG
;
3437 if (desc
->options
& ~(WS_FIELD_POINTER
| WS_FIELD_OPTIONAL
))
3439 FIXME( "options %08x not supported\n", desc
->options
);
3442 if (!(option
= get_field_read_option( desc
->type
))) return E_INVALIDARG
;
3444 if (option
== WS_READ_REQUIRED_VALUE
)
3445 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3447 size
= sizeof(void *);
3449 ptr
= buf
+ desc
->offset
;
3450 switch (desc
->mapping
)
3452 case WS_ATTRIBUTE_FIELD_MAPPING
:
3453 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
3454 desc
->typeDescription
, option
, heap
, ptr
, size
);
3457 case WS_ELEMENT_FIELD_MAPPING
:
3458 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
3459 desc
->typeDescription
, option
, heap
, ptr
, size
);
3462 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3465 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, size
, &count
);
3466 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
3469 case WS_TEXT_FIELD_MAPPING
:
3470 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
3474 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
3478 if (hr
== WS_E_INVALID_FORMAT
&& desc
->options
& WS_FIELD_OPTIONAL
)
3482 case WS_READ_REQUIRED_VALUE
:
3483 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
3484 else memset( ptr
, 0, size
);
3487 case WS_READ_REQUIRED_POINTER
:
3488 *(void **)ptr
= NULL
;
3492 ERR( "unhandled option %u\n", option
);
3500 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3501 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3502 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3503 WS_HEAP
*heap
, void *ret
, ULONG size
)
3509 if (!desc
) return E_INVALIDARG
;
3511 if (desc
->structOptions
)
3513 FIXME( "struct options %08x not supported\n", desc
->structOptions
);
3519 case WS_READ_REQUIRED_POINTER
:
3520 case WS_READ_OPTIONAL_POINTER
:
3521 if (size
!= sizeof(void *)) return E_INVALIDARG
;
3522 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
3525 case WS_READ_REQUIRED_VALUE
:
3526 if (size
!= desc
->size
) return E_INVALIDARG
;
3531 FIXME( "unhandled read option %u\n", option
);
3535 for (i
= 0; i
< desc
->fieldCount
; i
++)
3537 if ((hr
= read_type_struct_field( reader
, desc
->fields
[i
], heap
, buf
)) != S_OK
)
3543 case WS_READ_REQUIRED_POINTER
:
3546 ws_free( heap
, buf
);
3549 *(char **)ret
= buf
;
3552 case WS_READ_OPTIONAL_POINTER
:
3555 ws_free( heap
, buf
);
3558 *(char **)ret
= buf
;
3561 case WS_READ_REQUIRED_VALUE
:
3565 ERR( "unhandled read option %u\n", option
);
3570 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3571 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3572 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
,
3573 void *value
, ULONG size
)
3579 case WS_ELEMENT_TYPE_MAPPING
:
3580 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3581 if ((hr
= read_type_next_element_node( reader
, localname
, ns
)) != S_OK
) return hr
;
3584 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3585 case WS_ATTRIBUTE_TYPE_MAPPING
:
3589 FIXME( "unhandled mapping %u\n", mapping
);
3595 case WS_STRUCT_TYPE
:
3596 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3601 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3606 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3611 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3616 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3621 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3626 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3630 case WS_UINT16_TYPE
:
3631 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3635 case WS_UINT32_TYPE
:
3636 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3640 case WS_UINT64_TYPE
:
3641 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3645 case WS_DOUBLE_TYPE
:
3646 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3651 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3656 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3660 case WS_DATETIME_TYPE
:
3661 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3666 if ((hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3671 FIXME( "type %u not supported\n", type
);
3677 case WS_ELEMENT_TYPE_MAPPING
:
3678 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3679 return read_type_next_node( reader
);
3681 case WS_ATTRIBUTE_TYPE_MAPPING
:
3687 /**************************************************************************
3688 * WsReadType [webservices.@]
3690 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3691 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
3692 ULONG size
, WS_ERROR
*error
)
3694 struct reader
*reader
= (struct reader
*)handle
;
3697 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
3699 if (error
) FIXME( "ignoring error parameter\n" );
3701 if (!reader
|| !value
) return E_INVALIDARG
;
3703 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
3708 case WS_ELEMENT_TYPE_MAPPING
:
3709 if ((hr
= read_node( reader
)) != S_OK
) return hr
;
3716 if (!read_end_of_data( reader
)) return WS_E_INVALID_FORMAT
;
3720 /**************************************************************************
3721 * WsReadElement [webservices.@]
3723 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3724 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
3727 struct reader
*reader
= (struct reader
*)handle
;
3729 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
3730 if (error
) FIXME( "ignoring error parameter\n" );
3732 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
3734 return read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
3735 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
3738 /**************************************************************************
3739 * WsReadValue [webservices.@]
3741 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
3744 struct reader
*reader
= (struct reader
*)handle
;
3745 WS_TYPE type
= map_value_type( value_type
);
3747 TRACE( "%p %u %p %u %p\n", handle
, type
, value
, size
, error
);
3748 if (error
) FIXME( "ignoring error parameter\n" );
3750 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
3752 return read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
3753 NULL
, value
, size
);
3756 /**************************************************************************
3757 * WsSetErrorProperty [webservices.@]
3759 HRESULT WINAPI
WsSetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, const void *value
,
3762 struct error
*error
= (struct error
*)handle
;
3764 TRACE( "%p %u %p %u\n", handle
, id
, value
, size
);
3766 if (id
== WS_ERROR_PROPERTY_LANGID
) return WS_E_INVALID_OPERATION
;
3767 return prop_set( error
->prop
, error
->prop_count
, id
, value
, size
);
3770 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
3772 static const char bom
[] = {0xef,0xbb,0xbf};
3773 const unsigned char *p
= data
;
3775 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
3776 (size
> 2 && !(*offset
= 0));
3779 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
3781 static const char bom
[] = {0xff,0xfe};
3782 const unsigned char *p
= data
;
3784 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
3785 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
3788 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
3792 /* FIXME: parse xml declaration */
3794 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
3795 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
3798 FIXME( "charset not recognized\n" );
3802 TRACE( "detected charset %u\n", ret
);
3806 static void set_input_buffer( struct reader
*reader
, const unsigned char *data
, ULONG size
)
3808 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
3809 reader
->input_data
= data
;
3810 reader
->input_size
= size
;
3812 reader
->read_size
= reader
->input_size
;
3813 reader
->read_pos
= 0;
3814 reader
->read_bufptr
= reader
->input_data
;
3817 /**************************************************************************
3818 * WsSetInput [webservices.@]
3820 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
3821 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
3822 ULONG count
, WS_ERROR
*error
)
3824 struct reader
*reader
= (struct reader
*)handle
;
3827 ULONG i
, offset
= 0;
3829 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
3830 if (error
) FIXME( "ignoring error parameter\n" );
3832 if (!reader
) return E_INVALIDARG
;
3834 for (i
= 0; i
< count
; i
++)
3836 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
3837 properties
[i
].valueSize
);
3838 if (hr
!= S_OK
) return hr
;
3841 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
3843 switch (encoding
->encodingType
)
3845 case WS_XML_READER_ENCODING_TYPE_TEXT
:
3847 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
3848 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
3849 WS_CHARSET charset
= text
->charSet
;
3851 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
3853 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
3857 if (charset
== WS_CHARSET_AUTO
)
3858 charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
3860 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
3861 &charset
, sizeof(charset
) );
3862 if (hr
!= S_OK
) return hr
;
3866 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
3869 switch (input
->inputType
)
3871 case WS_XML_READER_INPUT_TYPE_BUFFER
:
3873 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
3874 set_input_buffer( reader
, (const unsigned char *)buf
->encodedData
+ offset
, buf
->encodedDataSize
- offset
);
3878 FIXME( "input type %u not supported\n", input
->inputType
);
3882 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
3883 read_insert_bof( reader
, node
);
3887 /**************************************************************************
3888 * WsSetInputToBuffer [webservices.@]
3890 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
3891 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
3894 struct reader
*reader
= (struct reader
*)handle
;
3895 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
3899 ULONG i
, offset
= 0;
3901 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
3902 if (error
) FIXME( "ignoring error parameter\n" );
3904 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
3906 for (i
= 0; i
< count
; i
++)
3908 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
3909 properties
[i
].valueSize
);
3910 if (hr
!= S_OK
) return hr
;
3913 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
3915 charset
= detect_charset( xmlbuf
->ptr
, xmlbuf
->size
, &offset
);
3916 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
3917 &charset
, sizeof(charset
) );
3918 if (hr
!= S_OK
) return hr
;
3920 set_input_buffer( reader
, (const unsigned char *)xmlbuf
->ptr
+ offset
, xmlbuf
->size
- offset
);
3921 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
3922 read_insert_bof( reader
, node
);
3926 /**************************************************************************
3927 * WsXmlStringEquals [webservices.@]
3929 HRESULT WINAPI
WsXmlStringEquals( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
, WS_ERROR
*error
)
3931 TRACE( "%s %s %p\n", debugstr_xmlstr(str1
), debugstr_xmlstr(str2
), error
);
3932 if (error
) FIXME( "ignoring error parameter\n" );
3934 if (!str1
|| !str2
) return E_INVALIDARG
;
3936 if (str1
->length
!= str2
->length
) return S_FALSE
;
3937 if (!memcmp( str1
->bytes
, str2
->bytes
, str1
->length
)) return S_OK
;