2 * Copyright 2015 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "webservices_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
32 const char *debugstr_xmlstr( const WS_XML_STRING
*str
)
34 if (!str
) return "(null)";
35 return debugstr_an( (const char *)str
->bytes
, str
->length
);
45 { sizeof(ULONG
), TRUE
}, /* WS_ERROR_PROPERTY_STRING_COUNT */
46 { sizeof(ULONG
), FALSE
}, /* WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE */
47 { sizeof(LANGID
), FALSE
} /* WS_ERROR_PROPERTY_LANGID */
53 WS_ERROR_PROPERTY prop
[sizeof(error_props
)/sizeof(error_props
[0])];
56 static struct error
*alloc_error(void)
58 static const ULONG count
= sizeof(error_props
)/sizeof(error_props
[0]);
60 ULONG i
, size
= sizeof(*ret
) + count
* sizeof(WS_ERROR_PROPERTY
);
63 for (i
= 0; i
< count
; i
++) size
+= error_props
[i
].size
;
64 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
66 ptr
= (char *)&ret
->prop
[count
];
67 for (i
= 0; i
< count
; i
++)
69 ret
->prop
[i
].value
= ptr
;
70 ret
->prop
[i
].valueSize
= error_props
[i
].size
;
71 ptr
+= ret
->prop
[i
].valueSize
;
73 ret
->prop_count
= count
;
77 static HRESULT
set_error_prop( struct error
*error
, WS_ERROR_PROPERTY_ID id
, const void *value
, ULONG size
)
79 if (id
>= error
->prop_count
|| size
!= error_props
[id
].size
|| error_props
[id
].readonly
)
82 memcpy( error
->prop
[id
].value
, value
, size
);
86 static HRESULT
get_error_prop( struct error
*error
, WS_ERROR_PROPERTY_ID id
, void *buf
, ULONG size
)
88 if (id
>= error
->prop_count
|| size
!= error_props
[id
].size
)
91 memcpy( buf
, error
->prop
[id
].value
, error
->prop
[id
].valueSize
);
95 /**************************************************************************
96 * WsCreateError [webservices.@]
98 HRESULT WINAPI
WsCreateError( const WS_ERROR_PROPERTY
*properties
, ULONG count
, WS_ERROR
**handle
)
101 LANGID langid
= GetUserDefaultUILanguage();
105 TRACE( "%p %u %p\n", properties
, count
, handle
);
107 if (!handle
) return E_INVALIDARG
;
108 if (!(error
= alloc_error())) return E_OUTOFMEMORY
;
110 set_error_prop( error
, WS_ERROR_PROPERTY_LANGID
, &langid
, sizeof(langid
) );
111 for (i
= 0; i
< count
; i
++)
113 if (properties
[i
].id
== WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE
)
118 hr
= set_error_prop( error
, properties
[i
].id
, properties
[i
].value
, properties
[i
].valueSize
);
126 *handle
= (WS_ERROR
*)error
;
130 /**************************************************************************
131 * WsFreeError [webservices.@]
133 void WINAPI
WsFreeError( WS_ERROR
*handle
)
135 struct error
*error
= (struct error
*)handle
;
137 TRACE( "%p\n", handle
);
148 { sizeof(SIZE_T
), FALSE
}, /* WS_HEAP_PROPERTY_MAX_SIZE */
149 { sizeof(SIZE_T
), FALSE
}, /* WS_HEAP_PROPERTY_TRIM_SIZE */
150 { sizeof(SIZE_T
), TRUE
}, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
151 { sizeof(SIZE_T
), TRUE
} /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
158 WS_HEAP_PROPERTY prop
[sizeof(heap_props
)/sizeof(heap_props
[0])];
161 void *ws_alloc( WS_HEAP
*handle
, SIZE_T size
)
163 struct heap
*heap
= (struct heap
*)handle
;
164 return HeapAlloc( heap
->handle
, 0, size
);
167 void *ws_realloc( WS_HEAP
*handle
, void *ptr
, SIZE_T size
)
169 struct heap
*heap
= (struct heap
*)handle
;
170 return HeapReAlloc( heap
->handle
, 0, ptr
, size
);
173 void ws_free( WS_HEAP
*handle
, void *ptr
)
175 struct heap
*heap
= (struct heap
*)handle
;
176 HeapFree( heap
->handle
, 0, ptr
);
179 /**************************************************************************
180 * WsAlloc [webservices.@]
182 HRESULT WINAPI
WsAlloc( WS_HEAP
*handle
, SIZE_T size
, void **ptr
, WS_ERROR
*error
)
186 TRACE( "%p %u %p %p\n", handle
, (ULONG
)size
, ptr
, error
);
187 if (error
) FIXME( "ignoring error parameter\n" );
189 if (!handle
|| !ptr
) return E_INVALIDARG
;
191 if (!(mem
= ws_alloc( handle
, size
))) return E_OUTOFMEMORY
;
196 static struct heap
*alloc_heap(void)
198 static const ULONG count
= sizeof(heap_props
)/sizeof(heap_props
[0]);
200 ULONG i
, size
= sizeof(*ret
) + count
* sizeof(WS_HEAP_PROPERTY
);
203 for (i
= 0; i
< count
; i
++) size
+= heap_props
[i
].size
;
204 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
206 ptr
= (char *)&ret
->prop
[count
];
207 for (i
= 0; i
< count
; i
++)
209 ret
->prop
[i
].value
= ptr
;
210 ret
->prop
[i
].valueSize
= heap_props
[i
].size
;
211 ptr
+= ret
->prop
[i
].valueSize
;
213 ret
->prop_count
= count
;
217 static HRESULT
set_heap_prop( struct heap
*heap
, WS_HEAP_PROPERTY_ID id
, const void *value
, ULONG size
)
219 if (id
>= heap
->prop_count
|| size
!= heap_props
[id
].size
|| heap_props
[id
].readonly
)
222 memcpy( heap
->prop
[id
].value
, value
, size
);
226 static HRESULT
get_heap_prop( struct heap
*heap
, WS_HEAP_PROPERTY_ID id
, void *buf
, ULONG size
)
228 if (id
>= heap
->prop_count
|| size
!= heap_props
[id
].size
)
231 memcpy( buf
, heap
->prop
[id
].value
, heap
->prop
[id
].valueSize
);
235 /**************************************************************************
236 * WsCreateHeap [webservices.@]
238 HRESULT WINAPI
WsCreateHeap( SIZE_T max_size
, SIZE_T trim_size
, const WS_HEAP_PROPERTY
*properties
,
239 ULONG count
, WS_HEAP
**handle
, WS_ERROR
*error
)
243 TRACE( "%u %u %p %u %p %p\n", (ULONG
)max_size
, (ULONG
)trim_size
, properties
, count
, handle
, error
);
244 if (error
) FIXME( "ignoring error parameter\n" );
246 if (!handle
|| count
) return E_INVALIDARG
;
247 if (!(heap
= alloc_heap())) return E_OUTOFMEMORY
;
249 set_heap_prop( heap
, WS_HEAP_PROPERTY_MAX_SIZE
, &max_size
, sizeof(max_size
) );
250 set_heap_prop( heap
, WS_HEAP_PROPERTY_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
252 if (!(heap
->handle
= HeapCreate( 0, 0, max_size
)))
255 return E_OUTOFMEMORY
;
258 *handle
= (WS_HEAP
*)heap
;
262 /**************************************************************************
263 * WsFreeHeap [webservices.@]
265 void WINAPI
WsFreeHeap( WS_HEAP
*handle
)
267 struct heap
*heap
= (struct heap
*)handle
;
269 TRACE( "%p\n", handle
);
272 HeapDestroy( heap
->handle
);
276 struct node
*alloc_node( WS_XML_NODE_TYPE type
)
280 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
281 ret
->hdr
.node
.nodeType
= type
;
282 list_init( &ret
->entry
);
283 list_init( &ret
->children
);
287 void free_attribute( WS_XML_ATTRIBUTE
*attr
)
290 heap_free( attr
->prefix
);
291 heap_free( attr
->localName
);
292 heap_free( attr
->ns
);
293 heap_free( attr
->value
);
297 void free_node( struct node
*node
)
300 switch (node
->hdr
.node
.nodeType
)
302 case WS_XML_NODE_TYPE_ELEMENT
:
304 WS_XML_ELEMENT_NODE
*elem
= (WS_XML_ELEMENT_NODE
*)node
;
307 for (i
= 0; i
< elem
->attributeCount
; i
++) free_attribute( elem
->attributes
[i
] );
308 heap_free( elem
->attributes
);
309 heap_free( elem
->prefix
);
310 heap_free( elem
->localName
);
311 heap_free( elem
->ns
);
314 case WS_XML_NODE_TYPE_TEXT
:
316 WS_XML_TEXT_NODE
*text
= (WS_XML_TEXT_NODE
*)node
;
317 heap_free( text
->text
);
320 case WS_XML_NODE_TYPE_COMMENT
:
322 WS_XML_COMMENT_NODE
*comment
= (WS_XML_COMMENT_NODE
*)node
;
323 heap_free( comment
->value
.bytes
);
325 case WS_XML_NODE_TYPE_END_ELEMENT
:
326 case WS_XML_NODE_TYPE_EOF
:
327 case WS_XML_NODE_TYPE_BOF
:
331 ERR( "unhandled type %u\n", node
->hdr
.node
.nodeType
);
337 void destroy_nodes( struct node
*node
)
342 while ((ptr
= list_head( &node
->children
)))
344 struct node
*child
= LIST_ENTRY( ptr
, struct node
, entry
);
345 list_remove( &child
->entry
);
346 destroy_nodes( child
);
358 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
359 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
360 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
361 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
362 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
363 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
364 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
365 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
366 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
367 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
368 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
369 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
370 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
371 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
372 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
377 READER_STATE_INITIAL
,
379 READER_STATE_STARTELEMENT
,
380 READER_STATE_STARTENDELEMENT
,
382 READER_STATE_ENDELEMENT
,
383 READER_STATE_COMMENT
,
391 const char *read_bufptr
;
392 enum reader_state state
;
394 struct node
*current
;
395 WS_XML_READER_INPUT_TYPE input_type
;
396 const char *input_data
;
399 WS_XML_READER_PROPERTY prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
402 static struct reader
*alloc_reader(void)
404 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
406 ULONG i
, size
= sizeof(*ret
) + count
* sizeof(WS_XML_READER_PROPERTY
);
409 for (i
= 0; i
< count
; i
++) size
+= reader_props
[i
].size
;
410 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
412 ptr
= (char *)&ret
->prop
[count
];
413 for (i
= 0; i
< count
; i
++)
415 ret
->prop
[i
].value
= ptr
;
416 ret
->prop
[i
].valueSize
= reader_props
[i
].size
;
417 ptr
+= ret
->prop
[i
].valueSize
;
419 ret
->prop_count
= count
;
423 static HRESULT
set_reader_prop( struct reader
*reader
, WS_XML_READER_PROPERTY_ID id
, const void *value
, ULONG size
)
425 if (id
>= reader
->prop_count
|| size
!= reader_props
[id
].size
|| reader_props
[id
].readonly
)
428 memcpy( reader
->prop
[id
].value
, value
, size
);
432 static HRESULT
get_reader_prop( struct reader
*reader
, WS_XML_READER_PROPERTY_ID id
, void *buf
, ULONG size
)
434 if (id
>= reader
->prop_count
|| size
!= reader_props
[id
].size
)
437 memcpy( buf
, reader
->prop
[id
].value
, reader
->prop
[id
].valueSize
);
441 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
443 if (!reader
->root
) reader
->root
= eof
;
446 eof
->parent
= reader
->root
;
447 list_add_tail( &reader
->root
->children
, &eof
->entry
);
449 reader
->current
= eof
;
452 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
454 reader
->root
->parent
= bof
;
455 list_add_tail( &bof
->children
, &reader
->root
->entry
);
456 reader
->current
= reader
->root
= bof
;
459 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
461 node
->parent
= parent
;
462 if (node
->parent
== reader
->root
)
464 struct list
*eof
= list_tail( &reader
->root
->children
);
465 list_add_before( eof
, &node
->entry
);
467 else list_add_tail( &parent
->children
, &node
->entry
);
468 reader
->current
= node
;
471 static HRESULT
read_init_state( struct reader
*reader
)
475 destroy_nodes( reader
->root
);
477 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
478 read_insert_eof( reader
, node
);
479 reader
->state
= READER_STATE_INITIAL
;
483 /**************************************************************************
484 * WsCreateReader [webservices.@]
486 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
487 WS_XML_READER
**handle
, WS_ERROR
*error
)
489 struct reader
*reader
;
490 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
491 WS_CHARSET charset
= WS_CHARSET_UTF8
;
492 BOOL read_decl
= TRUE
;
495 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
496 if (error
) FIXME( "ignoring error parameter\n" );
498 if (!handle
) return E_INVALIDARG
;
499 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
501 set_reader_prop( reader
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
502 set_reader_prop( reader
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
503 set_reader_prop( reader
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
504 set_reader_prop( reader
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
505 set_reader_prop( reader
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
507 for (i
= 0; i
< count
; i
++)
509 hr
= set_reader_prop( reader
, properties
[i
].id
, properties
[i
].value
, properties
[i
].valueSize
);
517 if ((hr
= read_init_state( reader
)) != S_OK
)
523 *handle
= (WS_XML_READER
*)reader
;
527 /**************************************************************************
528 * WsFreeReader [webservices.@]
530 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
532 struct reader
*reader
= (struct reader
*)handle
;
534 TRACE( "%p\n", handle
);
537 destroy_nodes( reader
->root
);
541 /**************************************************************************
542 * WsFillReader [webservices.@]
544 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
547 struct reader
*reader
= (struct reader
*)handle
;
549 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
550 if (error
) FIXME( "ignoring error parameter\n" );
552 if (!reader
) return E_INVALIDARG
;
554 /* FIXME: add support for stream input */
555 reader
->read_size
= min( min_size
, reader
->input_size
);
556 reader
->read_pos
= 0;
561 /**************************************************************************
562 * WsGetErrorProperty [webservices.@]
564 HRESULT WINAPI
WsGetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, void *buf
,
567 struct error
*error
= (struct error
*)handle
;
569 TRACE( "%p %u %p %u\n", handle
, id
, buf
, size
);
570 return get_error_prop( error
, id
, buf
, size
);
573 /**************************************************************************
574 * WsGetErrorString [webservices.@]
576 HRESULT WINAPI
WsGetErrorString( WS_ERROR
*handle
, ULONG index
, WS_STRING
*str
)
578 FIXME( "%p %u %p: stub\n", handle
, index
, str
);
582 /**************************************************************************
583 * WsGetHeapProperty [webservices.@]
585 HRESULT WINAPI
WsGetHeapProperty( WS_HEAP
*handle
, WS_HEAP_PROPERTY_ID id
, void *buf
,
586 ULONG size
, WS_ERROR
*error
)
588 struct heap
*heap
= (struct heap
*)handle
;
590 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
591 if (error
) FIXME( "ignoring error parameter\n" );
593 return get_heap_prop( heap
, id
, buf
, size
);
596 /**************************************************************************
597 * WsGetReaderNode [webservices.@]
599 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
602 struct reader
*reader
= (struct reader
*)handle
;
604 TRACE( "%p %p %p\n", handle
, node
, error
);
605 if (error
) FIXME( "ignoring error parameter\n" );
607 if (!reader
|| !node
) return E_INVALIDARG
;
609 *node
= &reader
->current
->hdr
.node
;
613 /**************************************************************************
614 * WsGetReaderProperty [webservices.@]
616 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
617 void *buf
, ULONG size
, WS_ERROR
*error
)
619 struct reader
*reader
= (struct reader
*)handle
;
621 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
622 if (error
) FIXME( "ignoring error parameter\n" );
624 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
626 if (id
== WS_XML_READER_PROPERTY_CHARSET
)
631 if ((hr
= get_reader_prop( reader
, id
, &charset
, size
)) != S_OK
) return hr
;
632 if (!charset
) return WS_E_INVALID_FORMAT
;
633 *(WS_CHARSET
*)buf
= charset
;
636 return get_reader_prop( reader
, id
, buf
, size
);
639 /**************************************************************************
640 * WsGetXmlAttribute [webservices.@]
642 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
643 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
645 FIXME( "%p %p %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
649 WS_XML_STRING
*alloc_xml_string( const char *data
, ULONG len
)
653 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
655 ret
->bytes
= (BYTE
*)(ret
+ 1);
656 ret
->dictionary
= NULL
;
658 if (data
) memcpy( ret
->bytes
, data
, len
);
662 static WS_XML_UTF8_TEXT
*alloc_utf8_text( const char *data
, ULONG len
)
664 WS_XML_UTF8_TEXT
*ret
;
666 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
667 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
668 ret
->value
.length
= len
;
669 ret
->value
.bytes
= (BYTE
*)(ret
+ 1);
670 ret
->value
.dictionary
= NULL
;
672 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
676 static inline BOOL
read_end_of_data( struct reader
*reader
)
678 return reader
->read_pos
>= reader
->read_size
;
681 static inline const char *read_current_ptr( struct reader
*reader
)
683 return &reader
->read_bufptr
[reader
->read_pos
];
686 /* UTF-8 support based on libs/wine/utf8.c */
688 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
689 static const char utf8_length
[128] =
691 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
692 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
693 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
694 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
695 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
696 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
697 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
698 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
701 /* first byte mask depending on UTF-8 sequence length */
702 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
704 /* minimum Unicode value depending on UTF-8 sequence length */
705 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
707 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
709 unsigned int len
, res
;
710 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
713 if (reader
->read_pos
>= reader
->read_size
) return 0;
720 len
= utf8_length
[ch
- 0x80];
721 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
722 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
;
723 res
= ch
& utf8_mask
[len
];
728 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
729 res
= (res
<< 6) | ch
;
731 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
732 res
= (res
<< 6) | ch
;
734 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
735 res
= (res
<< 6) | ch
;
736 if (res
< utf8_minval
[len
]) break;
744 static inline void read_skip( struct reader
*reader
, unsigned int count
)
746 while (reader
->read_pos
< reader
->read_size
&& count
)
753 static inline BOOL
read_isnamechar( unsigned int ch
)
755 /* FIXME: incomplete */
756 return (ch
>= 'A' && ch
<= 'Z') ||
757 (ch
>= 'a' && ch
<= 'z') ||
758 (ch
>= '0' && ch
<= '9') ||
759 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
762 static inline BOOL
read_isspace( unsigned int ch
)
764 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
767 static inline void read_skip_whitespace( struct reader
*reader
)
769 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
773 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
775 const char *ptr
= read_current_ptr( reader
);
777 if (len
< 0) len
= strlen( str
);
778 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
781 if (*str
!= *ptr
) return *ptr
- *str
;
787 static HRESULT
read_xmldecl( struct reader
*reader
)
789 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
791 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
793 reader
->state
= READER_STATE_BOF
;
796 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
797 read_skip( reader
, 6 );
799 /* FIXME: parse attributes */
800 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
803 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
804 read_skip( reader
, 2 );
806 reader
->state
= READER_STATE_BOF
;
810 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
812 if (elem
->attributeCount
)
814 WS_XML_ATTRIBUTE
**tmp
;
815 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
816 return E_OUTOFMEMORY
;
817 elem
->attributes
= tmp
;
819 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
820 elem
->attributes
[elem
->attributeCount
++] = attr
;
824 static HRESULT
read_attribute( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
826 WS_XML_ATTRIBUTE
*attr
;
827 WS_XML_UTF8_TEXT
*text
;
828 unsigned int len
= 0, ch
, skip
, quote
;
830 HRESULT hr
= WS_E_INVALID_FORMAT
;
832 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
834 start
= read_current_ptr( reader
);
837 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
838 if (!read_isnamechar( ch
)) break;
839 read_skip( reader
, skip
);
842 if (!len
) goto error
;
845 if (!(attr
->localName
= alloc_xml_string( start
, len
))) goto error
;
846 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 ))) goto error
;
847 attr
->prefix
->bytes
= NULL
;
848 if (!(attr
->ns
= alloc_xml_string( NULL
, 0 ))) goto error
;
849 attr
->ns
->bytes
= NULL
;
851 hr
= WS_E_INVALID_FORMAT
;
852 read_skip_whitespace( reader
);
853 if (read_cmp( reader
, "=", 1 )) goto error
;
854 read_skip( reader
, 1 );
856 read_skip_whitespace( reader
);
857 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) goto error
;
858 quote
= read_utf8_char( reader
, &skip
);
859 read_skip( reader
, 1 );
862 start
= read_current_ptr( reader
);
865 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
866 if (ch
== quote
) break;
867 read_skip( reader
, skip
);
870 read_skip( reader
, 1 );
872 if (!(text
= alloc_utf8_text( start
, len
)))
874 free_attribute( attr
);
875 return E_OUTOFMEMORY
;
877 attr
->value
= (WS_XML_TEXT
*)text
;
878 attr
->singleQuote
= (quote
== '\'');
884 free_attribute( attr
);
888 static HRESULT
read_element( struct reader
*reader
)
890 unsigned int len
= 0, ch
, skip
;
893 WS_XML_ELEMENT_NODE
*elem
;
894 WS_XML_ATTRIBUTE
*attr
;
895 HRESULT hr
= WS_E_INVALID_FORMAT
;
897 if (read_end_of_data( reader
))
899 struct list
*eof
= list_tail( &reader
->root
->children
);
900 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
901 reader
->state
= READER_STATE_EOF
;
905 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
906 elem
= (WS_XML_ELEMENT_NODE
*)node
;
908 if (read_cmp( reader
, "<", 1 )) goto error
;
909 read_skip( reader
, 1 );
911 start
= read_current_ptr( reader
);
914 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
915 if (!read_isnamechar( ch
)) break;
916 read_skip( reader
, skip
);
919 if (!len
) goto error
;
922 if (!(elem
->localName
= alloc_xml_string( start
, len
))) goto error
;
923 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 ))) goto error
;
924 elem
->prefix
->bytes
= NULL
;
925 if (!(elem
->ns
= alloc_xml_string( NULL
, 0 ))) goto error
;
929 read_skip_whitespace( reader
);
930 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
931 if ((hr
= read_attribute( reader
, &attr
)) != S_OK
) goto error
;
932 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
934 free_attribute( attr
);
939 read_skip_whitespace( reader
);
940 if (read_cmp( reader
, ">", 1 ) && read_cmp( reader
, "/>", 2 ))
942 hr
= WS_E_INVALID_FORMAT
;
946 read_insert_node( reader
, reader
->current
, node
);
947 if (!read_cmp( reader
, "/>", 2 ))
949 read_skip( reader
, 2 );
950 reader
->current
= reader
->current
->parent
;
951 reader
->state
= READER_STATE_STARTENDELEMENT
;
955 read_skip( reader
, 1 );
956 reader
->state
= READER_STATE_STARTELEMENT
;
965 static HRESULT
read_text( struct reader
*reader
)
967 unsigned int len
= 0, ch
, skip
;
970 WS_XML_TEXT_NODE
*text
;
971 WS_XML_UTF8_TEXT
*utf8
;
973 start
= read_current_ptr( reader
);
976 if (read_end_of_data( reader
)) break;
977 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
978 if (ch
== '<') break;
979 read_skip( reader
, skip
);
983 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
984 text
= (WS_XML_TEXT_NODE
*)node
;
985 if (!(utf8
= alloc_utf8_text( start
, len
)))
988 return E_OUTOFMEMORY
;
990 text
->text
= (WS_XML_TEXT
*)utf8
;
992 read_insert_node( reader
, reader
->current
, node
);
993 reader
->state
= READER_STATE_TEXT
;
997 static HRESULT
read_startelement( struct reader
*reader
)
999 if (!read_cmp( reader
, "<", 1 )) return read_element( reader
);
1000 return read_text( reader
);
1003 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
1007 switch (reader
->state
)
1009 case READER_STATE_INITIAL
:
1010 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
1013 case READER_STATE_STARTELEMENT
:
1014 if (found
) *found
= TRUE
;
1021 read_skip_whitespace( reader
);
1022 if ((hr
= read_element( reader
)) == S_OK
&& found
)
1024 if (reader
->state
== READER_STATE_STARTELEMENT
)
1033 static BOOL
cmp_localname( const char *name1
, ULONG len1
, const char *name2
, ULONG len2
)
1036 if (len1
!= len2
) return FALSE
;
1037 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return FALSE
; }
1041 static struct node
*find_parent_element( struct node
*node
, const char *localname
, ULONG len
)
1043 struct node
*parent
;
1044 WS_XML_STRING
*name
;
1046 for (parent
= node
; parent
; parent
= parent
->parent
)
1048 if (parent
->hdr
.node
.nodeType
!= WS_XML_NODE_TYPE_ELEMENT
) continue;
1049 name
= ((WS_XML_ELEMENT_NODE
*)parent
)->localName
;
1050 if (!cmp_localname( (const char *)name
->bytes
, name
->length
, localname
, len
)) continue;
1056 static HRESULT
read_endelement( struct reader
*reader
)
1058 struct node
*node
, *parent
;
1059 unsigned int len
= 0, ch
, skip
;
1062 switch (reader
->state
)
1064 case READER_STATE_TEXT
:
1065 case READER_STATE_STARTELEMENT
:
1066 case READER_STATE_STARTENDELEMENT
:
1069 return WS_E_INVALID_FORMAT
;
1072 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
1073 read_skip( reader
, 2 );
1075 start
= read_current_ptr( reader
);
1078 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1081 read_skip( reader
, 1 );
1084 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
1085 read_skip( reader
, skip
);
1088 if (!(parent
= find_parent_element( reader
->current
, start
, len
)))
1089 return WS_E_INVALID_FORMAT
;
1091 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1092 read_insert_node( reader
, parent
, node
);
1093 reader
->state
= READER_STATE_ENDELEMENT
;
1097 static HRESULT
read_comment( struct reader
*reader
)
1099 unsigned int len
= 0, ch
, skip
;
1102 WS_XML_COMMENT_NODE
*comment
;
1104 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
1105 read_skip( reader
, 4 );
1107 start
= read_current_ptr( reader
);
1110 if (!read_cmp( reader
, "-->", 3 ))
1112 read_skip( reader
, 3 );
1115 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1116 read_skip( reader
, skip
);
1120 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
1121 comment
= (WS_XML_COMMENT_NODE
*)node
;
1122 if (!(comment
->value
.bytes
= heap_alloc( len
)))
1125 return E_OUTOFMEMORY
;
1127 memcpy( comment
->value
.bytes
, start
, len
);
1128 comment
->value
.length
= len
;
1130 read_insert_node( reader
, reader
->current
, node
);
1131 reader
->state
= READER_STATE_COMMENT
;
1135 static HRESULT
read_node( struct reader
*reader
)
1141 if (read_end_of_data( reader
))
1143 struct list
*eof
= list_tail( &reader
->root
->children
);
1144 reader
->current
= LIST_ENTRY( eof
, struct node
, entry
);
1145 reader
->state
= READER_STATE_EOF
;
1148 if (!read_cmp( reader
, "<?", 2 ))
1150 hr
= read_xmldecl( reader
);
1151 if (FAILED( hr
)) return hr
;
1153 else if (!read_cmp( reader
, "</", 2 )) return read_endelement( reader
);
1154 else if (!read_cmp( reader
, "<!", 2 )) return read_comment( reader
);
1155 else if (!read_cmp( reader
, "<", 1 )) return read_startelement( reader
);
1156 else return read_text( reader
);
1160 /**************************************************************************
1161 * WsReadEndElement [webservices.@]
1163 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1165 struct reader
*reader
= (struct reader
*)handle
;
1167 TRACE( "%p %p\n", handle
, error
);
1168 if (error
) FIXME( "ignoring error parameter\n" );
1170 if (!reader
) return E_INVALIDARG
;
1171 return read_endelement( reader
);
1174 /**************************************************************************
1175 * WsReadNode [webservices.@]
1177 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
1179 struct reader
*reader
= (struct reader
*)handle
;
1181 TRACE( "%p %p\n", handle
, error
);
1182 if (error
) FIXME( "ignoring error parameter\n" );
1184 if (!reader
) return E_INVALIDARG
;
1185 return read_node( reader
);
1188 /**************************************************************************
1189 * WsReadStartElement [webservices.@]
1191 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1193 struct reader
*reader
= (struct reader
*)handle
;
1195 TRACE( "%p %p\n", handle
, error
);
1196 if (error
) FIXME( "ignoring error parameter\n" );
1198 if (!reader
) return E_INVALIDARG
;
1199 return read_startelement( reader
);
1202 /**************************************************************************
1203 * WsReadToStartElement [webservices.@]
1205 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
1206 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
1208 struct reader
*reader
= (struct reader
*)handle
;
1210 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
1211 if (error
) FIXME( "ignoring error parameter\n" );
1213 if (!reader
) return E_INVALIDARG
;
1214 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
1216 return read_to_startelement( reader
, found
);
1219 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
1222 BOOL success
= FALSE
;
1225 if (!read_end_of_data( reader
))
1227 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
1228 if (hr
!= S_OK
) return hr
;
1232 case WS_MOVE_TO_FIRST_NODE
:
1233 if ((ptr
= list_head( &reader
->current
->parent
->children
)))
1235 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1240 case WS_MOVE_TO_NEXT_NODE
:
1241 if ((ptr
= list_next( &reader
->current
->parent
->children
, &reader
->current
->entry
)))
1243 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1248 case WS_MOVE_TO_PREVIOUS_NODE
:
1249 if ((ptr
= list_prev( &reader
->current
->parent
->children
, &reader
->current
->entry
)))
1251 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1256 case WS_MOVE_TO_CHILD_NODE
:
1257 if ((ptr
= list_head( &reader
->current
->children
)))
1259 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1264 case WS_MOVE_TO_BOF
:
1265 reader
->current
= reader
->root
;
1269 case WS_MOVE_TO_EOF
:
1270 if ((ptr
= list_tail( &reader
->root
->children
)))
1272 reader
->current
= LIST_ENTRY( ptr
, struct node
, entry
);
1278 FIXME( "unhandled move %u\n", move
);
1287 return success
? S_OK
: WS_E_INVALID_FORMAT
;
1290 /**************************************************************************
1291 * WsMoveReader [webservices.@]
1293 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
1295 struct reader
*reader
= (struct reader
*)handle
;
1297 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
1298 if (error
) FIXME( "ignoring error parameter\n" );
1300 if (!reader
) return E_INVALIDARG
;
1301 if (!reader
->input_type
) return WS_E_INVALID_OPERATION
;
1303 return read_move_to( reader
, move
, found
);
1306 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
1310 switch (text
->textType
)
1312 case WS_XML_TEXT_TYPE_UTF8
:
1314 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1315 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
1316 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
1317 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
1322 FIXME( "unhandled type %u\n", text
->textType
);
1329 #define MAX_INT8 0x7f
1330 #define MIN_INT8 (-MAX_INT8 - 1)
1331 #define MAX_INT16 0x7fff
1332 #define MIN_INT16 (-MAX_INT16 - 1)
1333 #define MAX_INT32 0x7fffffff
1334 #define MIN_INT32 (-MAX_INT32 - 1)
1335 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1336 #define MIN_INT64 (-MAX_INT64 - 1)
1337 #define MAX_UINT8 0xff
1338 #define MAX_UINT16 0xffff
1339 #define MAX_UINT32 0xffffffff
1340 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1342 static HRESULT
str_to_int64( const char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
1344 BOOL negative
= FALSE
;
1345 const char *ptr
= str
;
1348 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
1349 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
1350 if (!len
) return WS_E_INVALID_FORMAT
;
1358 if (!len
) return WS_E_INVALID_FORMAT
;
1364 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
1366 if (negative
) val
= -val
;
1368 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
1369 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
1371 return WS_E_NUMERIC_OVERFLOW
;
1373 *ret
= *ret
* 10 + val
;
1380 static HRESULT
str_to_uint64( const char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
1382 const char *ptr
= str
;
1385 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
1386 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
1387 if (!len
) return WS_E_INVALID_FORMAT
;
1393 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
1396 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
1397 *ret
= *ret
* 10 + val
;
1404 /**************************************************************************
1405 * WsReadType [webservices.@]
1407 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1408 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
1409 ULONG value_size
, WS_ERROR
*error
)
1411 struct reader
*reader
= (struct reader
*)handle
;
1412 WS_XML_TEXT_NODE
*text
;
1414 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
1415 value_size
, error
);
1416 if (error
) FIXME( "ignoring error parameter\n" );
1418 if (!reader
|| !value
) return E_INVALIDARG
;
1420 if (reader
->current
->hdr
.node
.nodeType
!= WS_XML_NODE_TYPE_TEXT
)
1422 FIXME( "only text nodes are supported\n" );
1425 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
1426 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
1428 FIXME( "text type %u not supported\n", text
->text
->textType
);
1434 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1437 FIXME( "mapping %u not supported\n", mapping
);
1445 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1446 ULONG len
= utf8
->value
.length
;
1449 if (value_size
!= sizeof(BOOL
)) return E_INVALIDARG
;
1451 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) *ret
= TRUE
;
1452 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) *ret
= TRUE
;
1453 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) *ret
= FALSE
;
1454 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) *ret
= FALSE
;
1455 else return WS_E_INVALID_FORMAT
;
1460 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1465 if (value_size
!= sizeof(INT8
)) return E_INVALIDARG
;
1466 hr
= str_to_int64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
);
1467 if (hr
!= S_OK
) return hr
;
1473 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1478 if (value_size
!= sizeof(INT16
)) return E_INVALIDARG
;
1479 hr
= str_to_int64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
);
1480 if (hr
!= S_OK
) return hr
;
1486 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1491 if (value_size
!= sizeof(INT32
)) return E_INVALIDARG
;
1492 hr
= str_to_int64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
);
1493 if (hr
!= S_OK
) return hr
;
1499 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1500 INT64 val
, *ret
= value
;
1503 if (value_size
!= sizeof(INT64
)) return E_INVALIDARG
;
1504 hr
= str_to_int64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
);
1505 if (hr
!= S_OK
) return hr
;
1511 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1516 if (value_size
!= sizeof(UINT8
)) return E_INVALIDARG
;
1517 hr
= str_to_uint64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
);
1518 if (hr
!= S_OK
) return hr
;
1522 case WS_UINT16_TYPE
:
1524 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1525 UINT16
*ret
= value
;
1529 if (value_size
!= sizeof(UINT16
)) return E_INVALIDARG
;
1530 hr
= str_to_uint64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
);
1531 if (hr
!= S_OK
) return hr
;
1535 case WS_UINT32_TYPE
:
1537 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1538 UINT32
*ret
= value
;
1542 if (value_size
!= sizeof(UINT32
)) return E_INVALIDARG
;
1543 hr
= str_to_uint64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
);
1544 if (hr
!= S_OK
) return hr
;
1548 case WS_UINT64_TYPE
:
1550 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
->text
;
1551 UINT64 val
, *ret
= value
;
1554 if (value_size
!= sizeof(UINT64
)) return E_INVALIDARG
;
1555 hr
= str_to_uint64( (const char *)utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
);
1556 if (hr
!= S_OK
) return hr
;
1562 WCHAR
*str
, **ret
= value
;
1564 if (value_size
!= sizeof(WCHAR
*)) return E_INVALIDARG
;
1565 if (!(str
= xmltext_to_widechar( heap
, text
->text
))) return E_OUTOFMEMORY
;
1570 FIXME( "type %u not supported\n", type
);
1577 /**************************************************************************
1578 * WsSetErrorProperty [webservices.@]
1580 HRESULT WINAPI
WsSetErrorProperty( WS_ERROR
*handle
, WS_ERROR_PROPERTY_ID id
, const void *value
,
1583 struct error
*error
= (struct error
*)handle
;
1585 TRACE( "%p %u %p %u\n", handle
, id
, value
, size
);
1587 if (id
== WS_ERROR_PROPERTY_LANGID
) return WS_E_INVALID_OPERATION
;
1588 return set_error_prop( error
, id
, value
, size
);
1591 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
1593 static const char bom
[] = {0xef,0xbb,0xbf};
1594 const unsigned char *p
= data
;
1596 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
1597 (size
> 2 && !(*offset
= 0));
1600 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
1602 static const char bom
[] = {0xff,0xfe};
1603 const unsigned char *p
= data
;
1605 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
1606 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
1609 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
1613 /* FIXME: parse xml declaration */
1615 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
1616 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
1619 FIXME( "charset not recognized\n" );
1623 TRACE( "detected charset %u\n", ret
);
1627 static void set_input_buffer( struct reader
*reader
, const char *data
, ULONG size
)
1629 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
1630 reader
->input_data
= data
;
1631 reader
->input_size
= size
;
1633 reader
->read_size
= reader
->input_size
;
1634 reader
->read_pos
= 0;
1635 reader
->read_bufptr
= reader
->input_data
;
1638 /**************************************************************************
1639 * WsSetInput [webservices.@]
1641 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
1642 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
1643 ULONG count
, WS_ERROR
*error
)
1645 struct reader
*reader
= (struct reader
*)handle
;
1648 ULONG i
, offset
= 0;
1650 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
1651 if (error
) FIXME( "ignoring error parameter\n" );
1653 if (!reader
) return E_INVALIDARG
;
1655 for (i
= 0; i
< count
; i
++)
1657 hr
= set_reader_prop( reader
, properties
[i
].id
, properties
[i
].value
, properties
[i
].valueSize
);
1658 if (hr
!= S_OK
) return hr
;
1661 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
1663 switch (encoding
->encodingType
)
1665 case WS_XML_READER_ENCODING_TYPE_TEXT
:
1667 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
1668 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
1669 WS_CHARSET charset
= text
->charSet
;
1671 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
1673 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
1677 if (charset
== WS_CHARSET_AUTO
)
1678 charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
1680 hr
= set_reader_prop( reader
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
1681 if (hr
!= S_OK
) return hr
;
1685 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
1688 switch (input
->inputType
)
1690 case WS_XML_READER_INPUT_TYPE_BUFFER
:
1692 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
1693 set_input_buffer( reader
, (const char *)buf
->encodedData
+ offset
, buf
->encodedDataSize
- offset
);
1697 FIXME( "input type %u not supported\n", input
->inputType
);
1701 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
1702 read_insert_bof( reader
, node
);
1706 /**************************************************************************
1707 * WsSetInputToBuffer [webservices.@]
1709 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
1710 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
1713 struct reader
*reader
= (struct reader
*)handle
;
1714 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1718 ULONG i
, offset
= 0;
1720 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
1721 if (error
) FIXME( "ignoring error parameter\n" );
1723 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
1725 for (i
= 0; i
< count
; i
++)
1727 hr
= set_reader_prop( reader
, properties
[i
].id
, properties
[i
].value
, properties
[i
].valueSize
);
1728 if (hr
!= S_OK
) return hr
;
1731 if ((hr
= read_init_state( reader
)) != S_OK
) return hr
;
1733 charset
= detect_charset( xmlbuf
->ptr
, xmlbuf
->size
, &offset
);
1734 hr
= set_reader_prop( reader
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
1735 if (hr
!= S_OK
) return hr
;
1737 set_input_buffer( reader
, (const char *)xmlbuf
->ptr
+ offset
, xmlbuf
->size
- offset
);
1738 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
1739 read_insert_bof( reader
, node
);
1743 /**************************************************************************
1744 * WsXmlStringEquals [webservices.@]
1746 HRESULT WINAPI
WsXmlStringEquals( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
, WS_ERROR
*error
)
1748 TRACE( "%s %s %p\n", debugstr_xmlstr(str1
), debugstr_xmlstr(str2
), error
);
1749 if (error
) FIXME( "ignoring error parameter\n" );
1751 if (!str1
|| !str2
) return E_INVALIDARG
;
1753 if (str1
->length
!= str2
->length
) return S_FALSE
;
1754 if (!memcmp( str1
->bytes
, str2
->bytes
, str1
->length
)) return S_OK
;