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 static const struct prop_desc heap_props
[] =
147 { sizeof(SIZE_T
), FALSE
}, /* WS_HEAP_PROPERTY_MAX_SIZE */
148 { sizeof(SIZE_T
), FALSE
}, /* WS_HEAP_PROPERTY_TRIM_SIZE */
149 { sizeof(SIZE_T
), TRUE
}, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
150 { sizeof(SIZE_T
), TRUE
} /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
157 struct prop prop
[sizeof(heap_props
)/sizeof(heap_props
[0])];
160 static BOOL
ensure_heap( struct heap
*heap
)
163 if (heap
->handle
) return TRUE
;
164 if (prop_get( heap
->prop
, heap
->prop_count
, WS_HEAP_PROPERTY_MAX_SIZE
, &size
, sizeof(size
) ) != S_OK
)
166 if (!(heap
->handle
= HeapCreate( 0, 0, size
))) return FALSE
;
170 void *ws_alloc( WS_HEAP
*handle
, SIZE_T size
)
172 struct heap
*heap
= (struct heap
*)handle
;
173 if (!ensure_heap( heap
)) return NULL
;
174 return HeapAlloc( heap
->handle
, 0, size
);
177 static void *ws_alloc_zero( WS_HEAP
*handle
, SIZE_T size
)
179 struct heap
*heap
= (struct heap
*)handle
;
180 if (!ensure_heap( heap
)) return NULL
;
181 return HeapAlloc( heap
->handle
, HEAP_ZERO_MEMORY
, size
);
184 void *ws_realloc( WS_HEAP
*handle
, void *ptr
, SIZE_T size
)
186 struct heap
*heap
= (struct heap
*)handle
;
187 if (!ensure_heap( heap
)) return NULL
;
188 return HeapReAlloc( heap
->handle
, 0, ptr
, size
);
191 static void *ws_realloc_zero( WS_HEAP
*handle
, void *ptr
, SIZE_T size
)
193 struct heap
*heap
= (struct heap
*)handle
;
194 if (!ensure_heap( heap
)) return NULL
;
195 return HeapReAlloc( heap
->handle
, HEAP_ZERO_MEMORY
, ptr
, size
);
198 void ws_free( WS_HEAP
*handle
, void *ptr
)
200 struct heap
*heap
= (struct heap
*)handle
;
201 if (!heap
->handle
) return;
202 HeapFree( heap
->handle
, 0, ptr
);
205 /**************************************************************************
206 * WsAlloc [webservices.@]
208 HRESULT WINAPI
WsAlloc( WS_HEAP
*handle
, SIZE_T size
, void **ptr
, WS_ERROR
*error
)
212 TRACE( "%p %u %p %p\n", handle
, (ULONG
)size
, ptr
, error
);
213 if (error
) FIXME( "ignoring error parameter\n" );
215 if (!handle
|| !ptr
) return E_INVALIDARG
;
217 if (!(mem
= ws_alloc( handle
, size
))) return E_OUTOFMEMORY
;
222 static struct heap
*alloc_heap(void)
224 static const ULONG count
= sizeof(heap_props
)/sizeof(heap_props
[0]);
226 ULONG size
= sizeof(*ret
) + prop_size( heap_props
, count
);
228 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
229 prop_init( heap_props
, count
, ret
->prop
, &ret
[1] );
230 ret
->prop_count
= count
;
234 /**************************************************************************
235 * WsCreateHeap [webservices.@]
237 HRESULT WINAPI
WsCreateHeap( SIZE_T max_size
, SIZE_T trim_size
, const WS_HEAP_PROPERTY
*properties
,
238 ULONG count
, WS_HEAP
**handle
, WS_ERROR
*error
)
242 TRACE( "%u %u %p %u %p %p\n", (ULONG
)max_size
, (ULONG
)trim_size
, properties
, count
, handle
, error
);
243 if (error
) FIXME( "ignoring error parameter\n" );
245 if (!handle
|| count
) return E_INVALIDARG
;
246 if (!(heap
= alloc_heap())) return E_OUTOFMEMORY
;
248 prop_set( heap
->prop
, heap
->prop_count
, WS_HEAP_PROPERTY_MAX_SIZE
, &max_size
, sizeof(max_size
) );
249 prop_set( heap
->prop
, heap
->prop_count
, WS_HEAP_PROPERTY_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
251 *handle
= (WS_HEAP
*)heap
;
255 /**************************************************************************
256 * WsFreeHeap [webservices.@]
258 void WINAPI
WsFreeHeap( WS_HEAP
*handle
)
260 struct heap
*heap
= (struct heap
*)handle
;
262 TRACE( "%p\n", handle
);
265 HeapDestroy( heap
->handle
);
269 /**************************************************************************
270 * WsResetHeap [webservices.@]
272 HRESULT WINAPI
WsResetHeap( WS_HEAP
*handle
, WS_ERROR
*error
)
274 struct heap
*heap
= (struct heap
*)handle
;
276 TRACE( "%p %p\n", handle
, error
);
277 if (error
) FIXME( "ignoring error parameter\n" );
279 if (!heap
) return E_INVALIDARG
;
281 HeapDestroy( heap
->handle
);
286 struct node
*alloc_node( WS_XML_NODE_TYPE type
)
290 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
291 ret
->hdr
.node
.nodeType
= type
;
292 list_init( &ret
->entry
);
293 list_init( &ret
->children
);
297 void free_attribute( WS_XML_ATTRIBUTE
*attr
)
300 heap_free( attr
->prefix
);
301 heap_free( attr
->localName
);
302 heap_free( attr
->ns
);
303 heap_free( attr
->value
);
307 void free_node( struct node
*node
)
310 switch (node_type( node
))
312 case WS_XML_NODE_TYPE_ELEMENT
:
314 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
317 for (i
= 0; i
< elem
->attributeCount
; i
++) free_attribute( elem
->attributes
[i
] );
318 heap_free( elem
->attributes
);
319 heap_free( elem
->prefix
);
320 heap_free( elem
->localName
);
321 heap_free( elem
->ns
);
324 case WS_XML_NODE_TYPE_TEXT
:
326 WS_XML_TEXT_NODE
*text
= (WS_XML_TEXT_NODE
*)node
;
327 heap_free( text
->text
);
330 case WS_XML_NODE_TYPE_COMMENT
:
332 WS_XML_COMMENT_NODE
*comment
= (WS_XML_COMMENT_NODE
*)node
;
333 heap_free( comment
->value
.bytes
);
336 case WS_XML_NODE_TYPE_CDATA
:
337 case WS_XML_NODE_TYPE_END_CDATA
:
338 case WS_XML_NODE_TYPE_END_ELEMENT
:
339 case WS_XML_NODE_TYPE_EOF
:
340 case WS_XML_NODE_TYPE_BOF
:
344 ERR( "unhandled type %u\n", node_type( node
) );
350 void destroy_nodes( struct node
*node
)
355 while ((ptr
= list_head( &node
->children
)))
357 struct node
*child
= LIST_ENTRY( ptr
, struct node
, entry
);
358 list_remove( &child
->entry
);
359 destroy_nodes( child
);
364 static const struct prop_desc reader_props
[] =
366 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
367 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
368 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
369 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
370 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
371 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
372 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
373 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
374 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
375 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
376 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
377 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
378 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
379 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
380 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
385 READER_STATE_INITIAL
,
387 READER_STATE_STARTELEMENT
,
388 READER_STATE_STARTATTRIBUTE
,
389 READER_STATE_STARTCDATA
,
392 READER_STATE_ENDELEMENT
,
393 READER_STATE_ENDCDATA
,
394 READER_STATE_COMMENT
,
408 const unsigned char *read_bufptr
;
409 enum reader_state state
;
411 struct node
*current
;
414 struct prefix
*prefixes
;
416 ULONG nb_prefixes_allocated
;
417 WS_XML_READER_INPUT_TYPE input_type
;
418 const unsigned char *input_data
;
421 struct prop prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
424 static struct reader
*alloc_reader(void)
426 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
428 ULONG size
= sizeof(*ret
) + prop_size( reader_props
, count
);
430 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
431 if (!(ret
->prefixes
= heap_alloc_zero( sizeof(*ret
->prefixes
) )))
436 ret
->nb_prefixes
= ret
->nb_prefixes_allocated
= 1;
438 prop_init( reader_props
, count
, ret
->prop
, &ret
[1] );
439 ret
->prop_count
= count
;
443 static void clear_prefixes( struct prefix
*prefixes
, ULONG count
)
446 for (i
= 0; i
< count
; i
++)
448 heap_free( prefixes
[i
].str
.bytes
);
449 prefixes
[i
].str
.bytes
= NULL
;
450 prefixes
[i
].str
.length
= 0;
452 heap_free( prefixes
[i
].ns
.bytes
);
453 prefixes
[i
].ns
.bytes
= NULL
;
454 prefixes
[i
].ns
.length
= 0;
458 static void free_reader( struct reader
*reader
)
461 destroy_nodes( reader
->root
);
462 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
463 heap_free( reader
->prefixes
);
467 static HRESULT
set_prefix( struct prefix
*prefix
, const WS_XML_STRING
*str
, const WS_XML_STRING
*ns
)
471 heap_free( prefix
->str
.bytes
);
472 if (!(prefix
->str
.bytes
= heap_alloc( str
->length
))) return E_OUTOFMEMORY
;
473 memcpy( prefix
->str
.bytes
, str
->bytes
, str
->length
);
474 prefix
->str
.length
= str
->length
;
477 heap_free( prefix
->ns
.bytes
);
478 if (!(prefix
->ns
.bytes
= heap_alloc( ns
->length
))) return E_OUTOFMEMORY
;
479 memcpy( prefix
->ns
.bytes
, ns
->bytes
, ns
->length
);
480 prefix
->ns
.length
= ns
->length
;
485 static HRESULT
bind_prefix( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
*ns
)
490 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
492 if (WsXmlStringEquals( prefix
, &reader
->prefixes
[i
].str
, NULL
) == S_OK
)
493 return set_prefix( &reader
->prefixes
[i
], NULL
, ns
);
495 if (i
>= reader
->nb_prefixes_allocated
)
497 ULONG new_size
= reader
->nb_prefixes_allocated
* sizeof(*reader
->prefixes
) * 2;
498 struct prefix
*tmp
= heap_realloc_zero( reader
->prefixes
, new_size
);
499 if (!tmp
) return E_OUTOFMEMORY
;
500 reader
->prefixes
= tmp
;
501 reader
->nb_prefixes_allocated
*= 2;
504 if ((hr
= set_prefix( &reader
->prefixes
[i
], prefix
, ns
)) != S_OK
) return hr
;
505 reader
->nb_prefixes
++;
509 static const WS_XML_STRING
*get_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
)
512 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
514 if (WsXmlStringEquals( prefix
, &reader
->prefixes
[i
].str
, NULL
) == S_OK
)
515 return &reader
->prefixes
[i
].ns
;
520 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
522 if (!reader
->root
) reader
->root
= eof
;
525 eof
->parent
= reader
->root
;
526 list_add_tail( &reader
->root
->children
, &eof
->entry
);
528 reader
->current
= reader
->last
= eof
;
531 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
533 reader
->root
->parent
= bof
;
534 list_add_tail( &bof
->children
, &reader
->root
->entry
);
535 reader
->current
= reader
->last
= reader
->root
= bof
;
538 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
540 node
->parent
= parent
;
541 if (node
->parent
== reader
->root
)
543 struct list
*eof
= list_tail( &reader
->root
->children
);
544 list_add_before( eof
, &node
->entry
);
546 else list_add_tail( &parent
->children
, &node
->entry
);
547 reader
->current
= reader
->last
= node
;
550 static HRESULT
read_init_state( struct reader
*reader
)
554 destroy_nodes( reader
->root
);
556 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
557 reader
->nb_prefixes
= 1;
558 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
559 read_insert_eof( reader
, node
);
560 reader
->state
= READER_STATE_INITIAL
;
564 /**************************************************************************
565 * WsCreateReader [webservices.@]
567 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
568 WS_XML_READER
**handle
, WS_ERROR
*error
)
570 struct reader
*reader
;
571 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
572 WS_CHARSET charset
= WS_CHARSET_UTF8
;
573 BOOL read_decl
= TRUE
;
576 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
577 if (error
) FIXME( "ignoring error parameter\n" );
579 if (!handle
) return E_INVALIDARG
;
580 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
582 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
583 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
584 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
585 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
586 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
588 for (i
= 0; i
< count
; i
++)
590 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
591 properties
[i
].valueSize
);
594 free_reader( reader
);
599 if ((hr
= read_init_state( reader
)) != S_OK
)
601 free_reader( reader
);
605 *handle
= (WS_XML_READER
*)reader
;
609 /**************************************************************************
610 * WsFreeReader [webservices.@]
612 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
614 struct reader
*reader
= (struct reader
*)handle
;
616 TRACE( "%p\n", handle
);
617 free_reader( reader
);
620 /**************************************************************************
621 * WsFillReader [webservices.@]
623 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
626 struct reader
*reader
= (struct reader
*)handle
;
628 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
629 if (error
) FIXME( "ignoring error parameter\n" );
631 if (!reader
) return E_INVALIDARG
;
633 /* FIXME: add support for stream input */
634 reader
->read_size
= min( min_size
, reader
->input_size
);
635 reader
->read_pos
= 0;
640 /**************************************************************************
641 * WsGetErrorProperty [webservices.@]
643 HRESULT WINAPI
WsGetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, void *buf
,
646 struct error
*error
= (struct error
*)handle
;
648 TRACE( "%p %u %p %u\n", handle
, id
, buf
, size
);
649 return prop_get( error
->prop
, error
->prop_count
, id
, buf
, size
);
652 /**************************************************************************
653 * WsGetErrorString [webservices.@]
655 HRESULT WINAPI
WsGetErrorString( WS_ERROR
*handle
, ULONG index
, WS_STRING
*str
)
657 FIXME( "%p %u %p: stub\n", handle
, index
, str
);
661 /**************************************************************************
662 * WsGetHeapProperty [webservices.@]
664 HRESULT WINAPI
WsGetHeapProperty( WS_HEAP
*handle
, WS_HEAP_PROPERTY_ID id
, void *buf
,
665 ULONG size
, WS_ERROR
*error
)
667 struct heap
*heap
= (struct heap
*)handle
;
669 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
670 if (error
) FIXME( "ignoring error parameter\n" );
672 return prop_get( heap
->prop
, heap
->prop_count
, id
, buf
, size
);
675 /**************************************************************************
676 * WsGetNamespaceFromPrefix [webservices.@]
678 HRESULT WINAPI
WsGetNamespaceFromPrefix( WS_XML_READER
*handle
, const WS_XML_STRING
*prefix
,
679 BOOL required
, const WS_XML_STRING
**ns
, WS_ERROR
*error
)
681 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
682 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
683 static const WS_XML_STRING empty_ns
= {0, NULL
};
684 static const WS_XML_STRING xml_ns
= {36, (BYTE
*)"http://www.w3.org/XML/1998/namespace"};
685 static const WS_XML_STRING xmlns_ns
= {29, (BYTE
*)"http://www.w3.org/2000/xmlns/"};
686 struct reader
*reader
= (struct reader
*)handle
;
689 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(prefix
), required
, ns
, error
);
690 if (error
) FIXME( "ignoring error parameter\n" );
692 if (!reader
|| !prefix
|| !ns
) return E_INVALIDARG
;
693 if (reader
->state
!= READER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
700 else if (WsXmlStringEquals( prefix
, &xml
, NULL
) == S_OK
)
705 else if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
712 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
715 for (i
= 0; i
< elem
->attributeCount
; i
++)
717 if (!elem
->attributes
[i
]->isXmlNs
) continue;
718 if (WsXmlStringEquals( prefix
, elem
->attributes
[i
]->prefix
, NULL
) == S_OK
)
720 *ns
= elem
->attributes
[i
]->ns
;
729 if (required
) return WS_E_INVALID_FORMAT
;
736 /**************************************************************************
737 * WsGetReaderNode [webservices.@]
739 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
742 struct reader
*reader
= (struct reader
*)handle
;
744 TRACE( "%p %p %p\n", handle
, node
, error
);
745 if (error
) FIXME( "ignoring error parameter\n" );
747 if (!reader
|| !node
) return E_INVALIDARG
;
749 *node
= &reader
->current
->hdr
.node
;
753 /**************************************************************************
754 * WsGetReaderProperty [webservices.@]
756 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
757 void *buf
, ULONG size
, WS_ERROR
*error
)
759 struct reader
*reader
= (struct reader
*)handle
;
761 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
762 if (error
) FIXME( "ignoring error parameter\n" );
764 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
766 if (id
== WS_XML_READER_PROPERTY_CHARSET
)
771 if ((hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, &charset
, size
)) != S_OK
) return hr
;
772 if (!charset
) return WS_E_INVALID_FORMAT
;
773 *(WS_CHARSET
*)buf
= charset
;
776 return prop_get( reader
->prop
, reader
->prop_count
, id
, buf
, size
);
779 /**************************************************************************
780 * WsGetXmlAttribute [webservices.@]
782 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
783 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
785 FIXME( "%p %s %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
789 WS_XML_STRING
*alloc_xml_string( const unsigned char *data
, ULONG len
)
793 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
795 ret
->bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
796 ret
->dictionary
= NULL
;
798 if (data
) memcpy( ret
->bytes
, data
, len
);
802 WS_XML_UTF8_TEXT
*alloc_utf8_text( const unsigned char *data
, ULONG len
)
804 WS_XML_UTF8_TEXT
*ret
;
806 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
807 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
808 ret
->value
.length
= len
;
809 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
810 ret
->value
.dictionary
= NULL
;
812 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
816 static inline BOOL
read_end_of_data( struct reader
*reader
)
818 return reader
->read_pos
>= reader
->read_size
;
821 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
823 return &reader
->read_bufptr
[reader
->read_pos
];
826 /* UTF-8 support based on libs/wine/utf8.c */
828 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
829 static const char utf8_length
[128] =
831 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
832 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
833 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
834 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
835 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
836 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
837 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
838 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
841 /* first byte mask depending on UTF-8 sequence length */
842 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
844 /* minimum Unicode value depending on UTF-8 sequence length */
845 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
847 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
849 unsigned int len
, res
;
850 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
851 const unsigned char *end
;
853 if (reader
->read_pos
>= reader
->read_size
) return 0;
860 len
= utf8_length
[ch
- 0x80];
861 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
862 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
;
863 res
= ch
& utf8_mask
[len
];
868 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
869 res
= (res
<< 6) | ch
;
871 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
872 res
= (res
<< 6) | ch
;
874 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
875 res
= (res
<< 6) | ch
;
876 if (res
< utf8_minval
[len
]) break;
884 static inline void read_skip( struct reader
*reader
, unsigned int count
)
886 if (reader
->read_pos
+ count
> reader
->read_size
) return;
887 reader
->read_pos
+= count
;
890 static inline void read_rewind( struct reader
*reader
, unsigned int count
)
892 reader
->read_pos
-= count
;
895 static inline BOOL
read_isnamechar( unsigned int ch
)
897 /* FIXME: incomplete */
898 return (ch
>= 'A' && ch
<= 'Z') ||
899 (ch
>= 'a' && ch
<= 'z') ||
900 (ch
>= '0' && ch
<= '9') ||
901 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
904 static inline BOOL
read_isspace( unsigned int ch
)
906 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
909 static inline void read_skip_whitespace( struct reader
*reader
)
911 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
915 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
917 const unsigned char *ptr
= read_current_ptr( reader
);
919 if (len
< 0) len
= strlen( str
);
920 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
923 if (*str
!= *ptr
) return *ptr
- *str
;
929 static HRESULT
read_xmldecl( struct reader
*reader
)
931 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
933 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
935 reader
->state
= READER_STATE_BOF
;
938 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
939 read_skip( reader
, 6 );
941 /* FIXME: parse attributes */
942 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
945 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
946 read_skip( reader
, 2 );
948 reader
->state
= READER_STATE_BOF
;
952 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
954 if (elem
->attributeCount
)
956 WS_XML_ATTRIBUTE
**tmp
;
957 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
958 return E_OUTOFMEMORY
;
959 elem
->attributes
= tmp
;
961 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
962 elem
->attributes
[elem
->attributeCount
++] = attr
;
966 static HRESULT
parse_name( const unsigned char *str
, unsigned int len
,
967 WS_XML_STRING
**prefix
, WS_XML_STRING
**localname
)
969 const unsigned char *name_ptr
= str
, *prefix_ptr
= NULL
;
970 unsigned int i
, name_len
= len
, prefix_len
= 0;
972 for (i
= 0; i
< len
; i
++)
978 name_ptr
= &str
[i
+ 1];
983 if (!(*prefix
= alloc_xml_string( prefix_ptr
, prefix_len
))) return E_OUTOFMEMORY
;
984 if (!(*localname
= alloc_xml_string( name_ptr
, name_len
)))
986 heap_free( *prefix
);
987 return E_OUTOFMEMORY
;
992 static HRESULT
read_attribute( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
994 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
995 WS_XML_ATTRIBUTE
*attr
;
996 WS_XML_UTF8_TEXT
*text
;
997 unsigned int len
= 0, ch
, skip
, quote
;
998 const unsigned char *start
;
999 WS_XML_STRING
*prefix
, *localname
;
1000 HRESULT hr
= WS_E_INVALID_FORMAT
;
1002 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1004 start
= read_current_ptr( reader
);
1007 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1008 if (!read_isnamechar( ch
)) break;
1009 read_skip( reader
, skip
);
1012 if (!len
) goto error
;
1014 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1016 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1018 heap_free( prefix
);
1020 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1022 heap_free( localname
);
1025 attr
->localName
= localname
;
1027 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1030 attr
->prefix
= prefix
;
1031 attr
->localName
= localname
;
1035 attr
->prefix
= prefix
;
1036 attr
->localName
= localname
;
1039 hr
= WS_E_INVALID_FORMAT
;
1040 read_skip_whitespace( reader
);
1041 if (read_cmp( reader
, "=", 1 )) goto error
;
1042 read_skip( reader
, 1 );
1044 read_skip_whitespace( reader
);
1045 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) goto error
;
1046 quote
= read_utf8_char( reader
, &skip
);
1047 read_skip( reader
, 1 );
1050 start
= read_current_ptr( reader
);
1053 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1054 if (ch
== quote
) break;
1055 read_skip( reader
, skip
);
1058 read_skip( reader
, 1 );
1063 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1064 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1065 if (!(text
= alloc_utf8_text( NULL
, 0 ))) goto error
;
1067 else if (!(text
= alloc_utf8_text( start
, len
))) goto error
;
1069 attr
->value
= &text
->text
;
1070 attr
->singleQuote
= (quote
== '\'');
1076 free_attribute( attr
);
1080 static inline BOOL
is_valid_parent( const struct node
*node
)
1082 if (!node
) return FALSE
;
1083 return node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
|| node_type( node
) == WS_XML_NODE_TYPE_BOF
;
1086 static struct node
*read_find_parent( struct reader
*reader
)
1088 struct node
*node
= reader
->current
;
1089 if (node_type( node
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1091 if (!node
->parent
|| !is_valid_parent( node
->parent
->parent
)) return NULL
;
1092 return node
->parent
->parent
;
1094 else if (is_valid_parent( node
)) return node
;
1095 else if (is_valid_parent( node
->parent
)) return node
->parent
;
1099 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1101 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1102 const WS_XML_STRING
*ns
;
1105 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1106 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1107 if (!elem
->ns
->length
) elem
->ns
->bytes
= (BYTE
*)(elem
->ns
+ 1); /* quirk */
1109 for (i
= 0; i
< elem
->attributeCount
; i
++)
1111 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1112 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1113 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1114 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1119 static HRESULT
read_element( struct reader
*reader
)
1121 unsigned int len
= 0, ch
, skip
;
1122 const unsigned char *start
;
1123 struct node
*node
= NULL
, *parent
;
1124 WS_XML_ELEMENT_NODE
*elem
;
1125 WS_XML_ATTRIBUTE
*attr
= NULL
;
1126 HRESULT hr
= WS_E_INVALID_FORMAT
;
1128 if (read_end_of_data( reader
))
1130 struct list
*eof
= list_tail( &reader
->root
->children
);
1131 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
1132 reader
->state
= READER_STATE_EOF
;
1136 if (read_cmp( reader
, "<", 1 )) goto error
;
1137 read_skip( reader
, 1 );
1138 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1140 read_rewind( reader
, 1 );
1144 start
= read_current_ptr( reader
);
1147 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1148 if (!read_isnamechar( ch
)) break;
1149 read_skip( reader
, skip
);
1152 if (!len
) goto error
;
1154 if (!(parent
= read_find_parent( reader
))) goto error
;
1157 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) goto error
;
1158 elem
= (WS_XML_ELEMENT_NODE
*)node
;
1159 if ((hr
= parse_name( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1161 reader
->current_attr
= 0;
1164 read_skip_whitespace( reader
);
1165 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1166 if ((hr
= read_attribute( reader
, &attr
)) != S_OK
) goto error
;
1167 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1169 free_attribute( attr
);
1172 reader
->current_attr
++;
1174 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1176 read_insert_node( reader
, parent
, node
);
1177 reader
->state
= READER_STATE_STARTELEMENT
;
1185 static HRESULT
read_text( struct reader
*reader
)
1187 unsigned int len
= 0, ch
, skip
;
1188 const unsigned char *start
;
1189 struct node
*node
, *parent
;
1190 WS_XML_TEXT_NODE
*text
;
1191 WS_XML_UTF8_TEXT
*utf8
;
1193 start
= read_current_ptr( reader
);
1196 if (read_end_of_data( reader
)) break;
1197 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1198 if (ch
== '<') break;
1199 read_skip( reader
, skip
);
1203 if (!(parent
= read_find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1205 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1206 text
= (WS_XML_TEXT_NODE
*)node
;
1207 if (!(utf8
= alloc_utf8_text( start
, len
)))
1210 return E_OUTOFMEMORY
;
1212 text
->text
= &utf8
->text
;
1214 read_insert_node( reader
, parent
, node
);
1215 reader
->state
= READER_STATE_TEXT
;
1219 static HRESULT
read_node( struct reader
* );
1221 static HRESULT
read_startelement( struct reader
*reader
)
1225 read_skip_whitespace( reader
);
1226 if (!read_cmp( reader
, "/>", 2 ))
1228 read_skip( reader
, 2 );
1229 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1230 read_insert_node( reader
, reader
->current
, node
);
1231 reader
->state
= READER_STATE_ENDELEMENT
;
1234 else if (!read_cmp( reader
, ">", 1 ))
1236 read_skip( reader
, 1 );
1237 return read_node( reader
);
1239 return WS_E_INVALID_FORMAT
;
1242 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
1246 switch (reader
->state
)
1248 case READER_STATE_INITIAL
:
1249 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
1252 case READER_STATE_STARTELEMENT
:
1253 if (found
) *found
= TRUE
;
1260 read_skip_whitespace( reader
);
1261 if ((hr
= read_element( reader
)) == S_OK
&& found
)
1263 if (reader
->state
== READER_STATE_STARTELEMENT
)
1272 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
1275 if (len1
!= len2
) return 1;
1276 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
1280 static struct node
*read_find_start_element( struct reader
*reader
, const WS_XML_STRING
*prefix
,
1281 const WS_XML_STRING
*localname
)
1283 struct node
*parent
;
1284 const WS_XML_STRING
*str
;
1286 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
1288 if (node_type( parent
) == WS_XML_NODE_TYPE_BOF
) return NULL
;
1289 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1291 str
= parent
->hdr
.prefix
;
1292 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
1293 str
= parent
->hdr
.localName
;
1294 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
1302 static HRESULT
read_endelement( struct reader
*reader
)
1304 struct node
*node
, *parent
;
1305 unsigned int len
= 0, ch
, skip
;
1306 const unsigned char *start
;
1307 WS_XML_STRING
*prefix
, *localname
;
1310 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
1312 if (read_end_of_data( reader
))
1314 struct list
*eof
= list_tail( &reader
->root
->children
);
1315 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
1316 reader
->state
= READER_STATE_EOF
;
1320 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
1321 read_skip( reader
, 2 );
1323 start
= read_current_ptr( reader
);
1326 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1329 read_skip( reader
, 1 );
1332 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
1333 read_skip( reader
, skip
);
1337 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
1338 parent
= read_find_start_element( reader
, prefix
, localname
);
1339 heap_free( prefix
);
1340 heap_free( localname
);
1341 if (!parent
) return WS_E_INVALID_FORMAT
;
1343 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1344 read_insert_node( reader
, parent
, node
);
1345 reader
->state
= READER_STATE_ENDELEMENT
;
1349 static HRESULT
read_comment( struct reader
*reader
)
1351 unsigned int len
= 0, ch
, skip
;
1352 const unsigned char *start
;
1353 struct node
*node
, *parent
;
1354 WS_XML_COMMENT_NODE
*comment
;
1356 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
1357 read_skip( reader
, 4 );
1359 start
= read_current_ptr( reader
);
1362 if (!read_cmp( reader
, "-->", 3 ))
1364 read_skip( reader
, 3 );
1367 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1368 read_skip( reader
, skip
);
1372 if (!(parent
= read_find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1374 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
1375 comment
= (WS_XML_COMMENT_NODE
*)node
;
1376 if (!(comment
->value
.bytes
= heap_alloc( len
)))
1379 return E_OUTOFMEMORY
;
1381 memcpy( comment
->value
.bytes
, start
, len
);
1382 comment
->value
.length
= len
;
1384 read_insert_node( reader
, parent
, node
);
1385 reader
->state
= READER_STATE_COMMENT
;
1389 static HRESULT
read_startcdata( struct reader
*reader
)
1391 struct node
*node
, *parent
;
1393 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
1394 read_skip( reader
, 9 );
1396 if (!(parent
= read_find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1398 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1399 read_insert_node( reader
, parent
, node
);
1400 reader
->state
= READER_STATE_STARTCDATA
;
1404 static HRESULT
read_cdata( struct reader
*reader
)
1406 unsigned int len
= 0, ch
, skip
;
1407 const unsigned char *start
;
1409 WS_XML_TEXT_NODE
*text
;
1410 WS_XML_UTF8_TEXT
*utf8
;
1412 start
= read_current_ptr( reader
);
1415 if (!read_cmp( reader
, "]]>", 3 )) break;
1416 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1417 read_skip( reader
, skip
);
1421 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1422 text
= (WS_XML_TEXT_NODE
*)node
;
1423 if (!(utf8
= alloc_utf8_text( start
, len
)))
1426 return E_OUTOFMEMORY
;
1428 text
->text
= &utf8
->text
;
1430 read_insert_node( reader
, reader
->current
, node
);
1431 reader
->state
= READER_STATE_CDATA
;
1435 static HRESULT
read_endcdata( struct reader
*reader
)
1439 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
1440 read_skip( reader
, 3 );
1442 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
1443 read_insert_node( reader
, reader
->current
->parent
, node
);
1444 reader
->state
= READER_STATE_ENDCDATA
;
1448 static HRESULT
read_node( struct reader
*reader
)
1454 if (read_end_of_data( reader
))
1456 struct list
*eof
= list_tail( &reader
->root
->children
);
1457 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
1458 reader
->state
= READER_STATE_EOF
;
1461 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
1462 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
1463 else if (!read_cmp( reader
, "<?", 2 ))
1465 hr
= read_xmldecl( reader
);
1466 if (FAILED( hr
)) return hr
;
1468 else if (!read_cmp( reader
, "</", 2 )) return read_endelement( reader
);
1469 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
1470 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment( reader
);
1471 else if (!read_cmp( reader
, "<", 1 )) return read_element( reader
);
1472 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement( reader
);
1473 else return read_text( reader
);
1477 /**************************************************************************
1478 * WsReadEndElement [webservices.@]
1480 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1482 struct reader
*reader
= (struct reader
*)handle
;
1484 TRACE( "%p %p\n", handle
, error
);
1485 if (error
) FIXME( "ignoring error parameter\n" );
1487 if (!reader
) return E_INVALIDARG
;
1488 return read_endelement( reader
);
1491 /**************************************************************************
1492 * WsReadNode [webservices.@]
1494 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
1496 struct reader
*reader
= (struct reader
*)handle
;
1498 TRACE( "%p %p\n", handle
, error
);
1499 if (error
) FIXME( "ignoring error parameter\n" );
1501 if (!reader
) return E_INVALIDARG
;
1502 return read_node( reader
);
1505 /**************************************************************************
1506 * WsReadStartElement [webservices.@]
1508 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1510 struct reader
*reader
= (struct reader
*)handle
;
1512 TRACE( "%p %p\n", handle
, error
);
1513 if (error
) FIXME( "ignoring error parameter\n" );
1515 if (!reader
) return E_INVALIDARG
;
1516 return read_startelement( reader
);
1519 /**************************************************************************
1520 * WsReadToStartElement [webservices.@]
1522 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
1523 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
1525 struct reader
*reader
= (struct reader
*)handle
;
1527 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
1528 if (error
) FIXME( "ignoring error parameter\n" );
1530 if (!reader
) return E_INVALIDARG
;
1531 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
1533 return read_to_startelement( reader
, found
);
1536 static BOOL
move_to_root_element( struct reader
*reader
)
1541 if (!(ptr
= list_head( &reader
->root
->children
))) return FALSE
;
1542 node
= LIST_ENTRY( ptr
, struct node
, entry
);
1543 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
1545 reader
->current
= node
;
1548 while ((ptr
= list_next( &reader
->root
->children
, &node
->entry
)))
1550 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1551 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1553 reader
->current
= next
;
1561 static BOOL
move_to_next_element( struct reader
*reader
)
1564 struct node
*node
= reader
->current
;
1566 while ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
1568 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1569 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1571 reader
->current
= next
;
1579 static BOOL
move_to_prev_element( struct reader
*reader
)
1582 struct node
*node
= reader
->current
;
1584 while ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
1586 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
1587 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
1589 reader
->current
= prev
;
1597 static BOOL
move_to_child_element( struct reader
*reader
)
1602 if (!(ptr
= list_head( &reader
->current
->children
))) return FALSE
;
1603 node
= LIST_ENTRY( ptr
, struct node
, entry
);
1604 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
1606 reader
->current
= node
;
1609 while ((ptr
= list_next( &reader
->current
->children
, &node
->entry
)))
1611 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1612 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1614 reader
->current
= next
;
1622 static BOOL
move_to_end_element( struct reader
*reader
)
1625 struct node
*node
= reader
->current
;
1627 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
1629 if ((ptr
= list_tail( &node
->children
)))
1631 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
1632 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1634 reader
->current
= tail
;
1641 static BOOL
move_to_parent_element( struct reader
*reader
)
1643 struct node
*parent
= reader
->current
->parent
;
1645 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
1646 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
1648 reader
->current
= parent
;
1654 static BOOL
move_to_first_node( struct reader
*reader
)
1657 if ((ptr
= list_head( &reader
->current
->parent
->children
)))
1659 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1665 static BOOL
move_to_next_node( struct reader
*reader
)
1668 if ((ptr
= list_next( &reader
->current
->parent
->children
, &reader
->current
->entry
)))
1670 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1676 static BOOL
move_to_prev_node( struct reader
*reader
)
1679 if ((ptr
= list_prev( &reader
->current
->parent
->children
, &reader
->current
->entry
)))
1681 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1687 static BOOL
move_to_child_node( struct reader
*reader
)
1690 if ((ptr
= list_head( &reader
->current
->children
)))
1692 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1698 static BOOL
move_to_parent_node( struct reader
*reader
)
1700 struct node
*parent
= reader
->current
->parent
;
1701 if (!parent
) return FALSE
;
1702 reader
->current
= parent
;
1706 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
1709 BOOL success
= FALSE
;
1712 if (!read_end_of_data( reader
))
1714 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
1715 if (hr
!= S_OK
) return hr
;
1719 case WS_MOVE_TO_ROOT_ELEMENT
:
1720 success
= move_to_root_element( reader
);
1723 case WS_MOVE_TO_NEXT_ELEMENT
:
1724 success
= move_to_next_element( reader
);
1727 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
1728 success
= move_to_prev_element( reader
);
1731 case WS_MOVE_TO_CHILD_ELEMENT
:
1732 success
= move_to_child_element( reader
);
1735 case WS_MOVE_TO_END_ELEMENT
:
1736 success
= move_to_end_element( reader
);
1739 case WS_MOVE_TO_PARENT_ELEMENT
:
1740 success
= move_to_parent_element( reader
);
1743 case WS_MOVE_TO_FIRST_NODE
:
1744 success
= move_to_first_node( reader
);
1747 case WS_MOVE_TO_NEXT_NODE
:
1748 success
= move_to_next_node( reader
);
1751 case WS_MOVE_TO_PREVIOUS_NODE
:
1752 success
= move_to_prev_node( reader
);
1755 case WS_MOVE_TO_CHILD_NODE
:
1756 success
= move_to_child_node( reader
);
1759 case WS_MOVE_TO_BOF
:
1760 reader
->current
= reader
->root
;
1764 case WS_MOVE_TO_EOF
:
1765 if ((ptr
= list_tail( &reader
->root
->children
)))
1767 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1773 FIXME( "unhandled move %u\n", move
);
1782 return success
? S_OK
: WS_E_INVALID_FORMAT
;
1785 /**************************************************************************
1786 * WsMoveReader [webservices.@]
1788 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
1790 struct reader
*reader
= (struct reader
*)handle
;
1792 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
1793 if (error
) FIXME( "ignoring error parameter\n" );
1795 if (!reader
) return E_INVALIDARG
;
1796 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
1798 return read_move_to( reader
, move
, found
);
1801 /**************************************************************************
1802 * WsReadStartAttribute [webservices.@]
1804 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
1806 struct reader
*reader
= (struct reader
*)handle
;
1807 WS_XML_ELEMENT_NODE
*elem
;
1809 TRACE( "%p %u %p\n", handle
, index
, error
);
1810 if (error
) FIXME( "ignoring error parameter\n" );
1812 if (!reader
) return E_INVALIDARG
;
1814 elem
= &reader
->current
->hdr
;
1815 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
1816 return WS_E_INVALID_FORMAT
;
1818 reader
->current_attr
= index
;
1819 reader
->state
= READER_STATE_STARTATTRIBUTE
;
1823 /**************************************************************************
1824 * WsReadEndAttribute [webservices.@]
1826 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
1828 struct reader
*reader
= (struct reader
*)handle
;
1830 TRACE( "%p %p\n", handle
, error
);
1831 if (error
) FIXME( "ignoring error parameter\n" );
1833 if (!reader
) return E_INVALIDARG
;
1835 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
1836 return WS_E_INVALID_FORMAT
;
1838 reader
->state
= READER_STATE_STARTELEMENT
;
1842 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
1846 switch (text
->textType
)
1848 case WS_XML_TEXT_TYPE_UTF8
:
1850 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1851 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
1852 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
1853 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
1858 FIXME( "unhandled type %u\n", text
->textType
);
1865 #define MAX_INT8 0x7f
1866 #define MIN_INT8 (-MAX_INT8 - 1)
1867 #define MAX_INT16 0x7fff
1868 #define MIN_INT16 (-MAX_INT16 - 1)
1869 #define MAX_INT32 0x7fffffff
1870 #define MIN_INT32 (-MAX_INT32 - 1)
1871 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1872 #define MIN_INT64 (-MAX_INT64 - 1)
1873 #define MAX_UINT8 0xff
1874 #define MAX_UINT16 0xffff
1875 #define MAX_UINT32 0xffffffff
1876 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1878 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
1880 BOOL negative
= FALSE
;
1881 const unsigned char *ptr
= str
;
1884 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
1885 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
1886 if (!len
) return WS_E_INVALID_FORMAT
;
1894 if (!len
) return WS_E_INVALID_FORMAT
;
1900 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
1902 if (negative
) val
= -val
;
1904 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
1905 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
1907 return WS_E_NUMERIC_OVERFLOW
;
1909 *ret
= *ret
* 10 + val
;
1916 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
1918 const unsigned char *ptr
= str
;
1921 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
1922 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
1923 if (!len
) return WS_E_INVALID_FORMAT
;
1929 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
1932 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
1933 *ret
= *ret
* 10 + val
;
1940 #if defined(__i386__) || defined(__x86_64__)
1942 #define RC_DOWN 0x100;
1943 static BOOL
set_fp_rounding( unsigned short *save
)
1946 unsigned short fpword
;
1948 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
1951 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
1954 FIXME( "not implemented\n" );
1958 static void restore_fp_rounding( unsigned short fpword
)
1961 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
1963 FIXME( "not implemented\n" );
1967 static BOOL
set_fp_rounding( unsigned short *save
)
1969 FIXME( "not implemented\n" );
1972 static void restore_fp_rounding( unsigned short fpword
)
1974 FIXME( "not implemented\n" );
1978 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
1980 static const unsigned __int64 nan
= 0xfff8000000000000;
1981 static const unsigned __int64 inf
= 0x7ff0000000000000;
1982 static const unsigned __int64 inf_min
= 0xfff0000000000000;
1983 HRESULT hr
= WS_E_INVALID_FORMAT
;
1984 const unsigned char *p
= str
, *q
;
1985 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
1986 unsigned __int64 val
= 0, tmp
;
1987 long double exp_val
= 1.0, exp_mul
= 10.0;
1988 unsigned short fpword
;
1990 while (len
&& read_isspace( *p
)) { p
++; len
--; }
1991 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
1992 if (!len
) return WS_E_INVALID_FORMAT
;
1994 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
1996 *(unsigned __int64
*)ret
= nan
;
1999 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
2001 *(unsigned __int64
*)ret
= inf
;
2004 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
2006 *(unsigned __int64
*)ret
= inf_min
;
2016 else if (*p
== '+') { p
++; len
--; };
2017 if (!len
) return S_OK
;
2019 if (!set_fp_rounding( &fpword
)) return E_NOTIMPL
;
2022 while (len
&& isdigit( *q
)) { q
++; len
--; }
2023 have_digits
= nb_digits
= q
- p
;
2024 for (i
= 0; i
< nb_digits
; i
++)
2026 tmp
= val
* 10 + p
[i
] - '0';
2027 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
2029 for (; i
< nb_digits
; i
++) exp
++;
2040 while (len
&& isdigit( *q
)) { q
++; len
--; };
2041 have_digits
|= nb_digits
= q
- p
;
2042 for (i
= 0; i
< nb_digits
; i
++)
2044 tmp
= val
* 10 + p
[i
] - '0';
2045 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
2050 if (len
> 1 && tolower(*q
) == 'e')
2052 if (!have_digits
) goto done
;
2059 else if (*p
== '+') { p
++; len
--; };
2062 while (len
&& isdigit( *q
)) { q
++; len
--; };
2064 if (!nb_digits
|| len
) goto done
;
2065 for (i
= 0; i
< nb_digits
; i
++)
2067 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
2068 exp_tmp
= MAX_INT32
;
2070 exp_tmp
*= exp_sign
;
2072 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
2073 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
2074 else exp
+= exp_tmp
;
2077 if (!have_digits
|| len
) goto done
;
2079 if ((neg_exp
= exp
< 0)) exp
= -exp
;
2080 for (; exp
; exp
>>= 1)
2082 if (exp
& 1) exp_val
*= exp_mul
;
2086 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
2090 restore_fp_rounding( fpword
);
2094 #define TICKS_PER_SEC 10000000
2095 #define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
2096 #define TICKS_PER_HOUR (3600 * (ULONGLONG)TICKS_PER_SEC)
2097 #define TICKS_PER_DAY (86400 * (ULONGLONG)TICKS_PER_SEC)
2098 #define TICKS_MAX 3155378975999999999
2100 static const int month_offsets
[2][12] =
2102 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
2103 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
2106 static const int month_days
[2][12] =
2108 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
2109 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
2112 static inline int is_leap_year( int year
)
2114 return !(year
% 4) && (year
% 100 || !(year
% 400));
2117 static inline int valid_day( int year
, int month
, int day
)
2119 return day
> 0 && day
<= month_days
[is_leap_year( year
)][month
- 1];
2122 static inline int leap_days_before( int year
)
2124 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
2127 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
2129 const unsigned char *p
= bytes
, *q
;
2130 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
2132 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2133 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2136 while (len
&& isdigit( *q
)) { q
++; len
--; };
2137 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2138 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
2139 if (year
< 1) return WS_E_INVALID_FORMAT
;
2142 while (len
&& isdigit( *q
)) { q
++; len
--; };
2143 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2144 month
= (p
[0] - '0') * 10 + p
[1] - '0';
2145 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
2148 while (len
&& isdigit( *q
)) { q
++; len
--; };
2149 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
2150 day
= (p
[0] - '0') * 10 + p
[1] - '0';
2151 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
2154 while (len
&& isdigit( *q
)) { q
++; len
--; };
2155 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2156 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2157 if (hour
> 24) return WS_E_INVALID_FORMAT
;
2160 while (len
&& isdigit( *q
)) { q
++; len
--; };
2161 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2162 min
= (p
[0] - '0') * 10 + p
[1] - '0';
2163 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2166 while (len
&& isdigit( *q
)) { q
++; len
--; };
2167 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
2168 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
2169 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2173 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
2175 while (len
&& isdigit( *q
)) { q
++; len
--; };
2177 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
2178 for (i
= 0; i
< nb_digits
; i
++)
2180 sec_frac
+= (p
[i
] - '0') * mul
;
2186 if (--len
) return WS_E_INVALID_FORMAT
;
2187 tz_hour
= tz_min
= tz_neg
= 0;
2188 ret
->format
= WS_DATETIME_FORMAT_UTC
;
2190 else if (*q
== '+' || *q
== '-')
2192 tz_neg
= (*q
== '-') ? 1 : 0;
2195 while (len
&& isdigit( *q
)) { q
++; len
--; };
2196 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2197 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2198 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
2201 while (len
&& isdigit( *q
)) { q
++; len
--; };
2202 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
2203 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
2204 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
2206 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
2208 else return WS_E_INVALID_FORMAT
;
2210 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
2211 ret
->ticks
+= month_offsets
[is_leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
2212 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
2213 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
2214 ret
->ticks
+= min
* TICKS_PER_MIN
;
2215 ret
->ticks
+= sec
* TICKS_PER_SEC
;
2216 ret
->ticks
+= sec_frac
;
2220 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
2221 return WS_E_INVALID_FORMAT
;
2222 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
2223 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
2227 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
2228 return WS_E_INVALID_FORMAT
;
2229 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
2230 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
2236 #define TICKS_1601_01_01 504911232000000000
2238 /**************************************************************************
2239 * WsDateTimeToFileTime [webservices.@]
2241 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
2243 unsigned __int64 ticks
;
2245 TRACE( "%p %p %p\n", dt
, ft
, error
);
2246 if (error
) FIXME( "ignoring error parameter\n" );
2248 if (!dt
|| !ft
) return E_INVALIDARG
;
2250 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
2251 ticks
= dt
->ticks
- TICKS_1601_01_01
;
2252 ft
->dwHighDateTime
= ticks
>> 32;
2253 ft
->dwLowDateTime
= (DWORD
)ticks
;
2257 /**************************************************************************
2258 * WsFileTimeToDateTime [webservices.@]
2260 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
2262 unsigned __int64 ticks
;
2264 TRACE( "%p %p %p\n", ft
, dt
, error
);
2265 if (error
) FIXME( "ignoring error parameter\n" );
2267 if (!dt
|| !ft
) return E_INVALIDARG
;
2269 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
2270 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
2271 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
2272 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
2273 dt
->format
= WS_DATETIME_FORMAT_UTC
;
2277 static HRESULT
read_get_node_text( struct reader
*reader
, WS_XML_UTF8_TEXT
**ret
)
2279 WS_XML_TEXT_NODE
*text
;
2281 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
2282 return WS_E_INVALID_FORMAT
;
2284 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
2285 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2287 FIXME( "text type %u not supported\n", text
->text
->textType
);
2290 *ret
= (WS_XML_UTF8_TEXT
*)text
->text
;
2294 static HRESULT
read_get_attribute_text( struct reader
*reader
, ULONG index
, WS_XML_UTF8_TEXT
**ret
)
2296 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2297 WS_XML_ATTRIBUTE
*attr
;
2299 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2300 return WS_E_INVALID_FORMAT
;
2302 attr
= elem
->attributes
[index
];
2303 if (attr
->value
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2305 FIXME( "text type %u not supported\n", attr
->value
->textType
);
2308 *ret
= (WS_XML_UTF8_TEXT
*)attr
->value
;
2312 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
2313 const WS_XML_STRING
*ns
, ULONG
*index
)
2316 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2320 *index
= reader
->current_attr
;
2323 for (i
= 0; i
< elem
->attributeCount
; i
++)
2325 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
2326 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
2328 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
2329 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
2338 /**************************************************************************
2339 * WsFindAttribute [webservices.@]
2341 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2342 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
2345 struct reader
*reader
= (struct reader
*)handle
;
2347 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
2348 required
, index
, error
);
2349 if (error
) FIXME( "ignoring error parameter\n" );
2351 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
2353 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2354 return WS_E_INVALID_OPERATION
;
2356 if (!find_attribute( reader
, localname
, ns
, index
))
2358 if (required
) return WS_E_INVALID_FORMAT
;
2365 static HRESULT
read_get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2366 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2367 WS_XML_UTF8_TEXT
**ret
, BOOL
*found
)
2371 case WS_ATTRIBUTE_TYPE_MAPPING
:
2374 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
2375 return read_get_attribute_text( reader
, index
, ret
);
2377 case WS_ELEMENT_TYPE_MAPPING
:
2378 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2379 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2385 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2387 if (WsXmlStringEquals( localname
, elem
->localName
, NULL
) != S_OK
||
2388 WsXmlStringEquals( ns
, elem
->ns
, NULL
) != S_OK
)
2393 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
2395 return read_get_node_text( reader
, ret
);
2398 FIXME( "mapping %u not supported\n", mapping
);
2403 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2404 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2405 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2406 WS_HEAP
*heap
, void *ret
, ULONG size
)
2408 WS_XML_UTF8_TEXT
*utf8
;
2410 BOOL found
, val
= FALSE
;
2414 FIXME( "description not supported\n" );
2417 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2420 ULONG len
= utf8
->value
.length
;
2421 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
2422 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
2423 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
2424 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
2425 else return WS_E_INVALID_FORMAT
;
2430 case WS_READ_REQUIRED_VALUE
:
2431 if (!found
) return WS_E_INVALID_FORMAT
;
2432 if (size
!= sizeof(BOOL
)) return E_INVALIDARG
;
2436 case WS_READ_REQUIRED_POINTER
:
2437 if (!found
) return WS_E_INVALID_FORMAT
;
2440 case WS_READ_OPTIONAL_POINTER
:
2442 BOOL
*heap_val
= NULL
;
2443 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2446 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2449 *(BOOL
**)ret
= heap_val
;
2453 FIXME( "read option %u not supported\n", option
);
2460 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2461 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2462 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2463 WS_HEAP
*heap
, void *ret
, ULONG size
)
2465 WS_XML_UTF8_TEXT
*utf8
;
2472 FIXME( "description not supported\n" );
2475 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2476 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
2481 case WS_READ_REQUIRED_VALUE
:
2482 if (!found
) return WS_E_INVALID_FORMAT
;
2483 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
2487 case WS_READ_REQUIRED_POINTER
:
2488 if (!found
) return WS_E_INVALID_FORMAT
;
2491 case WS_READ_OPTIONAL_POINTER
:
2493 INT8
*heap_val
= NULL
;
2494 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2497 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2500 *(INT8
**)ret
= heap_val
;
2504 FIXME( "read option %u not supported\n", option
);
2511 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2512 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2513 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2514 WS_HEAP
*heap
, void *ret
, ULONG size
)
2516 WS_XML_UTF8_TEXT
*utf8
;
2523 FIXME( "description not supported\n" );
2526 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2527 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
2532 case WS_READ_REQUIRED_VALUE
:
2533 if (!found
) return WS_E_INVALID_FORMAT
;
2534 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
2535 *(INT16
*)ret
= val
;
2538 case WS_READ_REQUIRED_POINTER
:
2539 if (!found
) return WS_E_INVALID_FORMAT
;
2542 case WS_READ_OPTIONAL_POINTER
:
2544 INT16
*heap_val
= NULL
;
2545 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2548 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2551 *(INT16
**)ret
= heap_val
;
2555 FIXME( "read option %u not supported\n", option
);
2562 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2563 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2564 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2565 WS_HEAP
*heap
, void *ret
, ULONG size
)
2567 WS_XML_UTF8_TEXT
*utf8
;
2574 FIXME( "description not supported\n" );
2577 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2578 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
2583 case WS_READ_REQUIRED_VALUE
:
2584 if (!found
) return WS_E_INVALID_FORMAT
;
2585 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
2586 *(INT32
*)ret
= val
;
2589 case WS_READ_REQUIRED_POINTER
:
2590 if (!found
) return WS_E_INVALID_FORMAT
;
2593 case WS_READ_OPTIONAL_POINTER
:
2595 INT32
*heap_val
= NULL
;
2596 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2599 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2602 *(INT32
**)ret
= heap_val
;
2606 FIXME( "read option %u not supported\n", option
);
2613 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2614 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2615 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2616 WS_HEAP
*heap
, void *ret
, ULONG size
)
2618 WS_XML_UTF8_TEXT
*utf8
;
2625 FIXME( "description not supported\n" );
2628 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2629 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
2634 case WS_READ_REQUIRED_VALUE
:
2635 if (!found
) return WS_E_INVALID_FORMAT
;
2636 if (size
!= sizeof(INT64
)) return E_INVALIDARG
;
2637 *(INT64
*)ret
= val
;
2640 case WS_READ_REQUIRED_POINTER
:
2641 if (!found
) return WS_E_INVALID_FORMAT
;
2644 case WS_READ_OPTIONAL_POINTER
:
2646 INT64
*heap_val
= NULL
;
2647 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2650 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2653 *(INT64
**)ret
= heap_val
;
2657 FIXME( "read option %u not supported\n", option
);
2664 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2665 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2666 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2667 WS_HEAP
*heap
, void *ret
, ULONG size
)
2669 WS_XML_UTF8_TEXT
*utf8
;
2676 FIXME( "description not supported\n" );
2679 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2680 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
2685 case WS_READ_REQUIRED_VALUE
:
2686 if (!found
) return WS_E_INVALID_FORMAT
;
2687 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
2688 *(UINT8
*)ret
= val
;
2691 case WS_READ_REQUIRED_POINTER
:
2692 if (!found
) return WS_E_INVALID_FORMAT
;
2695 case WS_READ_OPTIONAL_POINTER
:
2697 UINT8
*heap_val
= NULL
;
2698 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2701 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2704 *(UINT8
**)ret
= heap_val
;
2708 FIXME( "read option %u not supported\n", option
);
2715 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2716 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2717 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2718 WS_HEAP
*heap
, void *ret
, ULONG size
)
2720 WS_XML_UTF8_TEXT
*utf8
;
2727 FIXME( "description not supported\n" );
2730 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2731 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
2736 case WS_READ_REQUIRED_VALUE
:
2737 if (!found
) return WS_E_INVALID_FORMAT
;
2738 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
2739 *(UINT16
*)ret
= val
;
2742 case WS_READ_REQUIRED_POINTER
:
2743 if (!found
) return WS_E_INVALID_FORMAT
;
2746 case WS_READ_OPTIONAL_POINTER
:
2748 UINT16
*heap_val
= NULL
;
2749 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2752 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2755 *(UINT16
**)ret
= heap_val
;
2759 FIXME( "read option %u not supported\n", option
);
2766 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2767 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2768 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2769 WS_HEAP
*heap
, void *ret
, ULONG size
)
2771 WS_XML_UTF8_TEXT
*utf8
;
2778 FIXME( "description not supported\n" );
2781 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2782 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
2787 case WS_READ_REQUIRED_VALUE
:
2788 if (!found
) return WS_E_INVALID_FORMAT
;
2789 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
2790 *(UINT32
*)ret
= val
;
2793 case WS_READ_REQUIRED_POINTER
:
2794 if (!found
) return WS_E_INVALID_FORMAT
;
2797 case WS_READ_OPTIONAL_POINTER
:
2799 UINT32
*heap_val
= NULL
;
2800 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2803 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2806 *(UINT32
**)ret
= heap_val
;
2810 FIXME( "read option %u not supported\n", option
);
2817 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2818 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2819 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2820 WS_HEAP
*heap
, void *ret
, ULONG size
)
2822 WS_XML_UTF8_TEXT
*utf8
;
2829 FIXME( "description not supported\n" );
2832 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2833 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
)) != S_OK
)
2838 case WS_READ_REQUIRED_VALUE
:
2839 if (!found
) return WS_E_INVALID_FORMAT
;
2840 if (size
!= sizeof(UINT64
)) return E_INVALIDARG
;
2841 *(UINT64
*)ret
= val
;
2844 case WS_READ_REQUIRED_POINTER
:
2845 if (!found
) return WS_E_INVALID_FORMAT
;
2848 case WS_READ_OPTIONAL_POINTER
:
2850 UINT64
*heap_val
= NULL
;
2851 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2854 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2857 *(UINT64
**)ret
= heap_val
;
2861 FIXME( "read option %u not supported\n", option
);
2868 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2869 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2870 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2871 WS_HEAP
*heap
, void *ret
, ULONG size
)
2873 WS_XML_UTF8_TEXT
*utf8
;
2878 if (desc
) FIXME( "ignoring description\n" );
2880 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2881 if (found
&& (hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
2885 case WS_READ_REQUIRED_VALUE
:
2886 if (!found
) return WS_E_INVALID_FORMAT
;
2887 if (size
!= sizeof(double)) return E_INVALIDARG
;
2888 *(double *)ret
= val
;
2891 case WS_READ_REQUIRED_POINTER
:
2892 if (!found
) return WS_E_INVALID_FORMAT
;
2895 case WS_READ_OPTIONAL_POINTER
:
2897 double *heap_val
= NULL
;
2898 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2901 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2904 *(double **)ret
= heap_val
;
2908 FIXME( "read option %u not supported\n", option
);
2915 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2916 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2917 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2918 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
2920 WS_XML_UTF8_TEXT
*utf8
;
2927 FIXME( "description not supported\n" );
2930 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2931 if (found
&& !(str
= xmltext_to_widechar( heap
, &utf8
->text
))) return WS_E_QUOTA_EXCEEDED
;
2935 case WS_READ_REQUIRED_POINTER
:
2936 if (!found
) return WS_E_INVALID_FORMAT
;
2939 case WS_READ_OPTIONAL_POINTER
:
2940 if (size
!= sizeof(str
)) return E_INVALIDARG
;
2945 FIXME( "read option %u not supported\n", option
);
2952 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
2955 for (i
= 0; i
< desc
->valueCount
; i
++)
2957 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
2959 *ret
= desc
->values
[i
].value
;
2963 return WS_E_INVALID_FORMAT
;
2966 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2967 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2968 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2969 WS_HEAP
*heap
, void *ret
, ULONG size
)
2971 WS_XML_UTF8_TEXT
*utf8
;
2976 if (!desc
) return E_INVALIDARG
;
2978 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2979 if (found
&& (hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
2983 case WS_READ_REQUIRED_VALUE
:
2984 if (!found
) return WS_E_INVALID_FORMAT
;
2985 if (size
!= sizeof(int)) return E_INVALIDARG
;
2989 case WS_READ_REQUIRED_POINTER
:
2990 if (!found
) return WS_E_INVALID_FORMAT
;
2993 case WS_READ_OPTIONAL_POINTER
:
2995 int *heap_val
= NULL
;
2996 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2999 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3002 *(int **)ret
= heap_val
;
3006 FIXME( "read option %u not supported\n", option
);
3013 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3014 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3015 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3016 WS_HEAP
*heap
, void *ret
, ULONG size
)
3018 WS_XML_UTF8_TEXT
*utf8
;
3020 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
3023 if (desc
) FIXME( "ignoring description\n" );
3025 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3026 if (found
&& (hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3030 case WS_READ_REQUIRED_VALUE
:
3031 if (!found
) return WS_E_INVALID_FORMAT
;
3032 if (size
!= sizeof(WS_DATETIME
)) return E_INVALIDARG
;
3033 *(WS_DATETIME
*)ret
= val
;
3036 case WS_READ_REQUIRED_POINTER
:
3037 if (!found
) return WS_E_INVALID_FORMAT
;
3040 case WS_READ_OPTIONAL_POINTER
:
3042 WS_DATETIME
*heap_val
= NULL
;
3043 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3046 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3049 *(WS_DATETIME
**)ret
= heap_val
;
3053 FIXME( "read option %u not supported\n", option
);
3060 static BOOL
is_empty_text_node( const struct node
*node
)
3062 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
3063 const WS_XML_UTF8_TEXT
*utf8
;
3066 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
3067 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3069 ERR( "unhandled text type %u\n", text
->text
->textType
);
3072 utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
3073 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
3077 static HRESULT
read_next_node( struct reader
*reader
)
3079 if (reader
->current
== reader
->last
) return read_node( reader
);
3080 if (move_to_child_node( reader
)) return S_OK
;
3081 if (move_to_next_node( reader
)) return S_OK
;
3082 if (!move_to_parent_node( reader
)) return WS_E_INVALID_FORMAT
;
3083 if (move_to_next_node( reader
)) return S_OK
;
3084 return WS_E_INVALID_FORMAT
;
3087 /* skips comment and empty text nodes */
3088 static HRESULT
read_type_next_node( struct reader
*reader
)
3093 WS_XML_NODE_TYPE type
;
3095 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3096 type
= node_type( reader
->current
);
3097 if (type
== WS_XML_NODE_TYPE_COMMENT
||
3098 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
3103 static BOOL
match_current_element( struct reader
*reader
, const WS_XML_STRING
*localname
,
3104 const WS_XML_STRING
*ns
)
3106 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3107 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
3108 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
3109 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
3112 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
3113 const WS_XML_STRING
*ns
)
3119 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
3120 if (reader
->current
== reader
->last
)
3123 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
3124 if (!found
) return WS_E_INVALID_FORMAT
;
3126 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3128 node
= reader
->current
;
3129 attr
= reader
->current_attr
;
3131 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
3132 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3134 reader
->current
= node
;
3135 reader
->current_attr
= attr
;
3137 return WS_E_INVALID_FORMAT
;
3140 static ULONG
get_type_size( WS_TYPE type
, const WS_STRUCT_DESCRIPTION
*desc
)
3146 return sizeof(INT8
);
3149 case WS_UINT16_TYPE
:
3150 return sizeof(INT16
);
3154 case WS_UINT32_TYPE
:
3156 return sizeof(INT32
);
3159 case WS_UINT64_TYPE
:
3160 return sizeof(INT64
);
3162 case WS_DOUBLE_TYPE
:
3163 return sizeof(double);
3165 case WS_DATETIME_TYPE
:
3166 return sizeof(WS_DATETIME
);
3169 return sizeof(WCHAR
*);
3171 case WS_STRUCT_TYPE
:
3175 ERR( "unhandled type %u\n", type
);
3180 static WS_READ_OPTION
get_array_read_option( WS_TYPE type
)
3190 case WS_UINT16_TYPE
:
3191 case WS_UINT32_TYPE
:
3192 case WS_UINT64_TYPE
:
3193 case WS_DOUBLE_TYPE
:
3195 case WS_STRUCT_TYPE
:
3196 case WS_DATETIME_TYPE
:
3197 return WS_READ_REQUIRED_VALUE
;
3200 return WS_READ_REQUIRED_POINTER
;
3203 FIXME( "unhandled type %u\n", type
);
3208 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
3209 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
3212 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3213 WS_HEAP
*heap
, void **ret
, ULONG size
, ULONG
*count
)
3216 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
3217 WS_READ_OPTION option
;
3220 if (size
!= sizeof(void *) || !(option
= get_array_read_option( desc
->type
))) return E_INVALIDARG
;
3222 /* wrapper element */
3223 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
3226 if (option
== WS_READ_REQUIRED_VALUE
)
3227 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
3229 item_size
= sizeof(void *);
3231 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
3234 if (nb_items
>= nb_allocated
)
3236 if (!(buf
= ws_realloc_zero( heap
, buf
, nb_allocated
* 2 * item_size
)))
3237 return WS_E_QUOTA_EXCEEDED
;
3240 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
3241 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
3242 if (hr
== WS_E_INVALID_FORMAT
) break;
3245 ws_free( heap
, buf
);
3248 offset
+= item_size
;
3252 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
3254 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
3256 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
3257 desc
->itemRange
->maxItemCount
);
3258 ws_free( heap
, buf
);
3259 return WS_E_INVALID_FORMAT
;
3268 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3269 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
3272 if (reader
->current
== reader
->last
)
3275 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
3276 if (!found
) return WS_E_INVALID_FORMAT
;
3278 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3279 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
3281 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
3282 desc
->typeDescription
, option
, heap
, ret
, size
);
3285 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
)
3295 case WS_UINT16_TYPE
:
3296 case WS_UINT32_TYPE
:
3297 case WS_UINT64_TYPE
:
3298 case WS_DOUBLE_TYPE
:
3300 case WS_DATETIME_TYPE
:
3301 return WS_READ_REQUIRED_VALUE
;
3304 case WS_STRUCT_TYPE
:
3305 return WS_READ_REQUIRED_POINTER
;
3308 FIXME( "unhandled type %u\n", type
);
3313 static HRESULT
read_type_struct_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3314 WS_HEAP
*heap
, char *buf
)
3317 WS_READ_OPTION option
;
3321 if (!desc
) return E_INVALIDARG
;
3322 if (desc
->options
& ~(WS_FIELD_POINTER
| WS_FIELD_OPTIONAL
))
3324 FIXME( "options %08x not supported\n", desc
->options
);
3327 if (!(option
= get_field_read_option( desc
->type
))) return E_INVALIDARG
;
3329 if (option
== WS_READ_REQUIRED_VALUE
)
3330 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3332 size
= sizeof(void *);
3334 ptr
= buf
+ desc
->offset
;
3335 switch (desc
->mapping
)
3337 case WS_ATTRIBUTE_FIELD_MAPPING
:
3338 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
3339 desc
->typeDescription
, option
, heap
, ptr
, size
);
3342 case WS_ELEMENT_FIELD_MAPPING
:
3343 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
3344 desc
->typeDescription
, option
, heap
, ptr
, size
);
3347 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3350 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, size
, &count
);
3351 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
3354 case WS_TEXT_FIELD_MAPPING
:
3355 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
3359 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
3363 if (hr
== WS_E_INVALID_FORMAT
&& desc
->options
& WS_FIELD_OPTIONAL
)
3367 case WS_READ_REQUIRED_VALUE
:
3368 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
3369 else memset( ptr
, 0, size
);
3372 case WS_READ_REQUIRED_POINTER
:
3373 *(void **)ptr
= NULL
;
3377 ERR( "unhandled option %u\n", option
);
3385 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3386 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3387 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3388 WS_HEAP
*heap
, void *ret
, ULONG size
)
3394 if (!desc
) return E_INVALIDARG
;
3396 if (desc
->structOptions
)
3398 FIXME( "struct options %08x not supported\n", desc
->structOptions
);
3404 case WS_READ_REQUIRED_POINTER
:
3405 case WS_READ_OPTIONAL_POINTER
:
3406 if (size
!= sizeof(void *)) return E_INVALIDARG
;
3407 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
3410 case WS_READ_REQUIRED_VALUE
:
3411 if (size
!= desc
->size
) return E_INVALIDARG
;
3416 FIXME( "unhandled read option %u\n", option
);
3420 for (i
= 0; i
< desc
->fieldCount
; i
++)
3422 if ((hr
= read_type_struct_field( reader
, desc
->fields
[i
], heap
, buf
)) != S_OK
)
3428 case WS_READ_REQUIRED_POINTER
:
3431 ws_free( heap
, buf
);
3434 *(char **)ret
= buf
;
3437 case WS_READ_OPTIONAL_POINTER
:
3440 ws_free( heap
, buf
);
3443 *(char **)ret
= buf
;
3446 case WS_READ_REQUIRED_VALUE
:
3450 ERR( "unhandled read option %u\n", option
);
3455 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3456 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3457 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
,
3458 void *value
, ULONG size
)
3464 case WS_ELEMENT_TYPE_MAPPING
:
3465 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3466 if ((hr
= read_type_next_element_node( reader
, localname
, ns
)) != S_OK
) return hr
;
3469 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3470 case WS_ATTRIBUTE_TYPE_MAPPING
:
3474 FIXME( "unhandled mapping %u\n", mapping
);
3480 case WS_STRUCT_TYPE
:
3481 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3486 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3491 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3496 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3501 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3506 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3511 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3515 case WS_UINT16_TYPE
:
3516 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3520 case WS_UINT32_TYPE
:
3521 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3525 case WS_UINT64_TYPE
:
3526 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3530 case WS_DOUBLE_TYPE
:
3531 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3536 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3541 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3545 case WS_DATETIME_TYPE
:
3546 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
3551 FIXME( "type %u not supported\n", type
);
3557 case WS_ELEMENT_TYPE_MAPPING
:
3558 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3559 return read_type_next_node( reader
);
3561 case WS_ATTRIBUTE_TYPE_MAPPING
:
3567 /**************************************************************************
3568 * WsReadType [webservices.@]
3570 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3571 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
3572 ULONG size
, WS_ERROR
*error
)
3574 struct reader
*reader
= (struct reader
*)handle
;
3577 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
3579 if (error
) FIXME( "ignoring error parameter\n" );
3581 if (!reader
|| !value
) return E_INVALIDARG
;
3583 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
3588 case WS_ELEMENT_TYPE_MAPPING
:
3589 if ((hr
= read_node( reader
)) != S_OK
) return hr
;
3596 if (!read_end_of_data( reader
)) return WS_E_INVALID_FORMAT
;
3600 /**************************************************************************
3601 * WsReadElement [webservices.@]
3603 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3604 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
3607 struct reader
*reader
= (struct reader
*)handle
;
3609 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
3610 if (error
) FIXME( "ignoring error parameter\n" );
3612 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
3614 return read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
3615 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
3618 /**************************************************************************
3619 * WsSetErrorProperty [webservices.@]
3621 HRESULT WINAPI
WsSetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, const void *value
,
3624 struct error
*error
= (struct error
*)handle
;
3626 TRACE( "%p %u %p %u\n", handle
, id
, value
, size
);
3628 if (id
== WS_ERROR_PROPERTY_LANGID
) return WS_E_INVALID_OPERATION
;
3629 return prop_set( error
->prop
, error
->prop_count
, id
, value
, size
);
3632 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
3634 static const char bom
[] = {0xef,0xbb,0xbf};
3635 const unsigned char *p
= data
;
3637 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
3638 (size
> 2 && !(*offset
= 0));
3641 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
3643 static const char bom
[] = {0xff,0xfe};
3644 const unsigned char *p
= data
;
3646 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
3647 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
3650 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
3654 /* FIXME: parse xml declaration */
3656 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
3657 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
3660 FIXME( "charset not recognized\n" );
3664 TRACE( "detected charset %u\n", ret
);
3668 static void set_input_buffer( struct reader
*reader
, const unsigned char *data
, ULONG size
)
3670 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
3671 reader
->input_data
= data
;
3672 reader
->input_size
= size
;
3674 reader
->read_size
= reader
->input_size
;
3675 reader
->read_pos
= 0;
3676 reader
->read_bufptr
= reader
->input_data
;
3679 /**************************************************************************
3680 * WsSetInput [webservices.@]
3682 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
3683 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
3684 ULONG count
, WS_ERROR
*error
)
3686 struct reader
*reader
= (struct reader
*)handle
;
3689 ULONG i
, offset
= 0;
3691 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
3692 if (error
) FIXME( "ignoring error parameter\n" );
3694 if (!reader
) return E_INVALIDARG
;
3696 for (i
= 0; i
< count
; i
++)
3698 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
3699 properties
[i
].valueSize
);
3700 if (hr
!= S_OK
) return hr
;
3703 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
3705 switch (encoding
->encodingType
)
3707 case WS_XML_READER_ENCODING_TYPE_TEXT
:
3709 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
3710 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
3711 WS_CHARSET charset
= text
->charSet
;
3713 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
3715 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
3719 if (charset
== WS_CHARSET_AUTO
)
3720 charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
3722 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
3723 &charset
, sizeof(charset
) );
3724 if (hr
!= S_OK
) return hr
;
3728 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
3731 switch (input
->inputType
)
3733 case WS_XML_READER_INPUT_TYPE_BUFFER
:
3735 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
3736 set_input_buffer( reader
, (const unsigned char *)buf
->encodedData
+ offset
, buf
->encodedDataSize
- offset
);
3740 FIXME( "input type %u not supported\n", input
->inputType
);
3744 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
3745 read_insert_bof( reader
, node
);
3749 /**************************************************************************
3750 * WsSetInputToBuffer [webservices.@]
3752 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
3753 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
3756 struct reader
*reader
= (struct reader
*)handle
;
3757 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
3761 ULONG i
, offset
= 0;
3763 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
3764 if (error
) FIXME( "ignoring error parameter\n" );
3766 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
3768 for (i
= 0; i
< count
; i
++)
3770 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
3771 properties
[i
].valueSize
);
3772 if (hr
!= S_OK
) return hr
;
3775 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
3777 charset
= detect_charset( xmlbuf
->ptr
, xmlbuf
->size
, &offset
);
3778 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
3779 &charset
, sizeof(charset
) );
3780 if (hr
!= S_OK
) return hr
;
3782 set_input_buffer( reader
, (const unsigned char *)xmlbuf
->ptr
+ offset
, xmlbuf
->size
- offset
);
3783 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
3784 read_insert_bof( reader
, node
);
3788 /**************************************************************************
3789 * WsXmlStringEquals [webservices.@]
3791 HRESULT WINAPI
WsXmlStringEquals( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
, WS_ERROR
*error
)
3793 TRACE( "%s %s %p\n", debugstr_xmlstr(str1
), debugstr_xmlstr(str2
), error
);
3794 if (error
) FIXME( "ignoring error parameter\n" );
3796 if (!str1
|| !str2
) return E_INVALIDARG
;
3798 if (str1
->length
!= str2
->length
) return S_FALSE
;
3799 if (!memcmp( str1
->bytes
, str2
->bytes
, str1
->length
)) return S_OK
;