2 * IXmlReader implementation
4 * Copyright 2010, 2012 Nikolay Sivov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "xmllite_private.h"
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(xmllite);
36 /* not defined in public headers */
37 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
46 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
47 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
49 static const WCHAR dblquoteW[] = {'\"',0};
50 static const WCHAR quoteW[] = {'\'',0};
52 struct xml_encoding_data
59 static const struct xml_encoding_data xml_encoding_map[] = {
60 { utf16W, XmlEncoding_UTF16, ~0 },
61 { utf8W, XmlEncoding_UTF8, CP_UTF8 }
68 unsigned int allocated;
72 typedef struct input_buffer input_buffer;
74 typedef struct _xmlreaderinput
76 IXmlReaderInput IXmlReaderInput_iface;
78 /* reference passed on IXmlReaderInput creation, is kept when input is created */
81 xml_encoding encoding;
84 /* stream reference set after SetInput() call from reader,
85 stored as sequential stream, cause currently
86 optimizations possible with IStream aren't implemented */
87 ISequentialStream *stream;
91 typedef struct _xmlreader
93 IXmlReader IXmlReader_iface;
95 xmlreaderinput *input;
99 DtdProcessing dtdmode;
100 UINT line, pos; /* reader position in XML stream */
105 encoded_buffer utf16;
106 encoded_buffer encoded;
108 xmlreaderinput *input;
111 static inline xmlreader *impl_from_IXmlReader(IXmlReader *iface)
113 return CONTAINING_RECORD(iface, xmlreader, IXmlReader_iface);
116 static inline xmlreaderinput *impl_from_IXmlReaderInput(IXmlReaderInput *iface)
118 return CONTAINING_RECORD(iface, xmlreaderinput, IXmlReaderInput_iface);
121 static inline void *m_alloc(IMalloc *imalloc, size_t len)
124 return IMalloc_Alloc(imalloc, len);
126 return heap_alloc(len);
129 static inline void *m_realloc(IMalloc *imalloc, void *mem, size_t len)
132 return IMalloc_Realloc(imalloc, mem, len);
134 return heap_realloc(mem, len);
137 static inline void m_free(IMalloc *imalloc, void *mem)
140 IMalloc_Free(imalloc, mem);
145 /* reader memory allocation functions */
146 static inline void *reader_alloc(xmlreader *reader, size_t len)
148 return m_alloc(reader->imalloc, len);
151 static inline void reader_free(xmlreader *reader, void *mem)
153 m_free(reader->imalloc, mem);
156 /* reader input memory allocation functions */
157 static inline void *readerinput_alloc(xmlreaderinput *input, size_t len)
159 return m_alloc(input->imalloc, len);
162 static inline void *readerinput_realloc(xmlreaderinput *input, void *mem, size_t len)
164 return m_realloc(input->imalloc, mem, len);
167 static inline void readerinput_free(xmlreaderinput *input, void *mem)
169 m_free(input->imalloc, mem);
172 static inline WCHAR *readerinput_strdupW(xmlreaderinput *input, const WCHAR *str)
179 size = (strlenW(str)+1)*sizeof(WCHAR);
180 ret = readerinput_alloc(input, size);
181 if (ret) memcpy(ret, str, size);
187 static HRESULT init_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer)
189 const int initial_len = 0x2000;
190 buffer->data = readerinput_alloc(input, initial_len);
191 if (!buffer->data) return E_OUTOFMEMORY;
193 memset(buffer->data, 0, 4);
194 buffer->cur = buffer->data;
195 buffer->allocated = initial_len;
201 static void free_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer)
203 readerinput_free(input, buffer->data);
206 static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
208 if (encoding == XmlEncoding_Unknown)
210 FIXME("unsupported encoding %d\n", encoding);
214 *cp = xml_encoding_map[encoding].cp;
219 static xml_encoding parse_encoding_name(const WCHAR *name, int len)
223 if (!name) return XmlEncoding_Unknown;
226 max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
233 c = strncmpiW(xml_encoding_map[n].name, name, len);
235 c = strcmpiW(xml_encoding_map[n].name, name);
237 return xml_encoding_map[n].enc;
245 return XmlEncoding_Unknown;
248 static HRESULT alloc_input_buffer(xmlreaderinput *input)
250 input_buffer *buffer;
253 input->buffer = NULL;
255 buffer = readerinput_alloc(input, sizeof(*buffer));
256 if (!buffer) return E_OUTOFMEMORY;
258 buffer->input = input;
259 buffer->code_page = ~0; /* code page is unknown at this point */
260 hr = init_encoded_buffer(input, &buffer->utf16);
262 readerinput_free(input, buffer);
266 hr = init_encoded_buffer(input, &buffer->encoded);
268 free_encoded_buffer(input, &buffer->utf16);
269 readerinput_free(input, buffer);
273 input->buffer = buffer;
277 static void free_input_buffer(input_buffer *buffer)
279 free_encoded_buffer(buffer->input, &buffer->encoded);
280 free_encoded_buffer(buffer->input, &buffer->utf16);
281 readerinput_free(buffer->input, buffer);
284 static void readerinput_release_stream(xmlreaderinput *readerinput)
286 if (readerinput->stream) {
287 ISequentialStream_Release(readerinput->stream);
288 readerinput->stream = NULL;
292 /* Queries already stored interface for IStream/ISequentialStream.
293 Interface supplied on creation will be overwritten */
294 static HRESULT readerinput_query_for_stream(xmlreaderinput *readerinput)
298 readerinput_release_stream(readerinput);
299 hr = IUnknown_QueryInterface(readerinput->input, &IID_IStream, (void**)&readerinput->stream);
301 hr = IUnknown_QueryInterface(readerinput->input, &IID_ISequentialStream, (void**)&readerinput->stream);
306 /* reads a chunk to raw buffer */
307 static HRESULT readerinput_growraw(xmlreaderinput *readerinput)
309 encoded_buffer *buffer = &readerinput->buffer->encoded;
310 ULONG len = buffer->allocated - buffer->written, read;
313 /* always try to get aligned to 4 bytes, so the only case we can get partialy read characters is
314 variable width encodings like UTF-8 */
315 len = (len + 3) & ~3;
316 /* try to use allocated space or grow */
317 if (buffer->allocated - buffer->written < len)
319 buffer->allocated *= 2;
320 buffer->data = readerinput_realloc(readerinput, buffer->data, buffer->allocated);
321 len = buffer->allocated - buffer->written;
324 hr = ISequentialStream_Read(readerinput->stream, buffer->data + buffer->written, len, &read);
325 if (FAILED(hr)) return hr;
326 TRACE("requested %d, read %d, ret 0x%08x\n", len, read, hr);
327 buffer->written += read;
332 /* grows UTF-16 buffer so it has at least 'length' bytes free on return */
333 static void readerinput_grow(xmlreaderinput *readerinput, int length)
335 encoded_buffer *buffer = &readerinput->buffer->utf16;
337 /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
338 if (buffer->allocated < buffer->written + length + 4)
340 int grown_size = max(2*buffer->allocated, buffer->allocated + length);
341 buffer->data = readerinput_realloc(readerinput, buffer->data, grown_size);
342 buffer->allocated = grown_size;
346 static HRESULT readerinput_detectencoding(xmlreaderinput *readerinput, xml_encoding *enc)
348 encoded_buffer *buffer = &readerinput->buffer->encoded;
349 static char startA[] = {'<','?','x','m'};
350 static WCHAR startW[] = {'<','?'};
351 static char utf8bom[] = {0xef,0xbb,0xbf};
352 static char utf16lebom[] = {0xff,0xfe};
354 *enc = XmlEncoding_Unknown;
356 if (buffer->written <= 3) return MX_E_INPUTEND;
358 /* try start symbols if we have enough data to do that, input buffer should contain
359 first chunk already */
360 if (!memcmp(buffer->data, startA, sizeof(startA)))
361 *enc = XmlEncoding_UTF8;
362 else if (!memcmp(buffer->data, startW, sizeof(startW)))
363 *enc = XmlEncoding_UTF16;
364 /* try with BOM now */
365 else if (!memcmp(buffer->data, utf8bom, sizeof(utf8bom)))
367 buffer->cur += sizeof(utf8bom);
368 *enc = XmlEncoding_UTF8;
370 else if (!memcmp(buffer->data, utf16lebom, sizeof(utf16lebom)))
372 buffer->cur += sizeof(utf16lebom);
373 *enc = XmlEncoding_UTF16;
379 static int readerinput_get_utf8_convlen(xmlreaderinput *readerinput)
381 encoded_buffer *buffer = &readerinput->buffer->encoded;
382 int len = buffer->written;
384 /* complete single byte char */
385 if (!(buffer->data[len-1] & 0x80)) return len;
387 /* find start byte of multibyte char */
388 while (--len && !(buffer->data[len] & 0xc0))
394 /* returns byte length of complete char sequence for specified code page, */
395 static int readerinput_get_convlen(xmlreaderinput *readerinput, UINT cp)
397 encoded_buffer *buffer = &readerinput->buffer->encoded;
398 int len = buffer->written;
401 len = readerinput_get_utf8_convlen(readerinput);
403 len = buffer->written;
405 return len - (buffer->cur - buffer->data);
408 /* note that raw buffer content is kept */
409 static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding enc)
411 encoded_buffer *src = &readerinput->buffer->encoded;
412 encoded_buffer *dest = &readerinput->buffer->utf16;
417 hr = get_code_page(enc, &cp);
418 if (FAILED(hr)) return;
420 len = readerinput_get_convlen(readerinput, cp);
422 TRACE("switching to cp %d\n", cp);
424 /* just copy in this case */
425 if (enc == XmlEncoding_UTF16)
427 readerinput_grow(readerinput, len);
428 memcpy(dest->data, src->cur, len);
429 readerinput->buffer->code_page = cp;
433 dest_len = MultiByteToWideChar(cp, 0, src->cur, len, NULL, 0);
434 readerinput_grow(readerinput, dest_len);
435 MultiByteToWideChar(cp, 0, src->cur, len, (WCHAR*)dest->data, dest_len);
436 dest->data[dest_len] = 0;
437 readerinput->buffer->code_page = cp;
440 static inline const WCHAR *reader_get_cur(xmlreader *reader)
442 return (WCHAR*)reader->input->buffer->utf16.cur;
445 static int reader_cmp(xmlreader *reader, const WCHAR *str)
447 const WCHAR *ptr = reader_get_cur(reader);
450 return strncmpW(str, ptr, strlenW(str));
453 if (ptr[i] != str[i]) return 0;
460 /* moves cursor n WCHARs forward */
461 static void reader_skipn(xmlreader *reader, int n)
463 encoded_buffer *buffer = &reader->input->buffer->utf16;
464 const WCHAR *ptr = reader_get_cur(reader);
466 while (*ptr++ && n--)
468 buffer->cur += sizeof(WCHAR);
473 /* [3] S ::= (#x20 | #x9 | #xD | #xA)+ */
474 static int reader_skipspaces(xmlreader *reader)
476 encoded_buffer *buffer = &reader->input->buffer->utf16;
477 const WCHAR *ptr = reader_get_cur(reader), *start = ptr;
479 while (*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n')
481 buffer->cur += sizeof(WCHAR);
484 else if (*ptr == '\n')
497 /* [26] VersionNum ::= '1.' [0-9]+ */
498 static HRESULT reader_parse_versionnum(xmlreader *reader)
500 const WCHAR *ptr, *ptr2, *start = reader_get_cur(reader);
501 static const WCHAR onedotW[] = {'1','.',0};
503 if (reader_cmp(reader, onedotW)) return WC_E_XMLDECL;
505 reader_skipn(reader, 2);
507 ptr2 = ptr = reader_get_cur(reader);
508 while (*ptr >= '0' && *ptr <= '9')
511 if (ptr2 == ptr) return WC_E_DIGIT;
512 TRACE("version=%s\n", debugstr_wn(start, ptr-start));
513 reader_skipn(reader, ptr-ptr2);
517 /* [25] Eq ::= S? '=' S? */
518 static HRESULT reader_parse_eq(xmlreader *reader)
520 static const WCHAR eqW[] = {'=',0};
521 reader_skipspaces(reader);
522 if (reader_cmp(reader, eqW)) return WC_E_EQUAL;
524 reader_skipn(reader, 1);
525 reader_skipspaces(reader);
529 /* [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') */
530 static HRESULT reader_parse_versioninfo(xmlreader *reader)
532 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
535 if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
537 if (reader_cmp(reader, versionW)) return WC_E_XMLDECL;
539 reader_skipn(reader, 7);
541 hr = reader_parse_eq(reader);
542 if (FAILED(hr)) return hr;
544 if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
547 reader_skipn(reader, 1);
549 hr = reader_parse_versionnum(reader);
550 if (FAILED(hr)) return hr;
552 if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
556 reader_skipn(reader, 1);
561 /* ([A-Za-z0-9._] | '-') */
562 static inline int is_wchar_encname(WCHAR ch)
564 return ((ch >= 'A' && ch <= 'Z') ||
565 (ch >= 'a' && ch <= 'z') ||
566 (ch >= '0' && ch <= '9') ||
567 (ch == '.') || (ch == '_') ||
571 /* [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* */
572 static HRESULT reader_parse_encname(xmlreader *reader)
574 const WCHAR *start = reader_get_cur(reader), *ptr;
578 if ((*start < 'A' || *start > 'Z') && (*start < 'a' || *start > 'z'))
582 while (is_wchar_encname(*++ptr))
586 enc = parse_encoding_name(start, len);
587 TRACE("encoding name %s\n", debugstr_wn(start, len));
589 if (enc == XmlEncoding_Unknown)
592 /* skip encoding name */
593 reader_skipn(reader, len);
597 /* [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ) */
598 static HRESULT reader_parse_encdecl(xmlreader *reader)
600 static const WCHAR encodingW[] = {'e','n','c','o','d','i','n','g',0};
603 if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
605 if (reader_cmp(reader, encodingW)) return S_FALSE;
606 /* skip 'encoding' */
607 reader_skipn(reader, 8);
609 hr = reader_parse_eq(reader);
610 if (FAILED(hr)) return hr;
612 if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
615 reader_skipn(reader, 1);
617 hr = reader_parse_encname(reader);
618 if (FAILED(hr)) return hr;
620 if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
624 reader_skipn(reader, 1);
629 /* [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) */
630 static HRESULT reader_parse_sddecl(xmlreader *reader)
632 static const WCHAR standaloneW[] = {'s','t','a','n','d','a','l','o','n','e',0};
633 static const WCHAR yesW[] = {'y','e','s',0};
634 static const WCHAR noW[] = {'n','o',0};
635 const WCHAR *start, *ptr;
638 if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
640 if (reader_cmp(reader, standaloneW)) return S_FALSE;
641 /* skip 'standalone' */
642 reader_skipn(reader, 10);
644 hr = reader_parse_eq(reader);
645 if (FAILED(hr)) return hr;
647 if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
650 reader_skipn(reader, 1);
652 if (reader_cmp(reader, yesW) && reader_cmp(reader, noW))
655 start = reader_get_cur(reader);
656 /* skip 'yes'|'no' */
657 reader_skipn(reader, reader_cmp(reader, yesW) ? 2 : 3);
658 ptr = reader_get_cur(reader);
659 TRACE("standalone=%s\n", debugstr_wn(start, ptr-start));
661 if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
664 reader_skipn(reader, 1);
669 /* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
670 static HRESULT reader_parse_xmldecl(xmlreader *reader)
672 static const WCHAR xmldeclW[] = {'<','?','x','m','l',0};
673 static const WCHAR declcloseW[] = {'?','>',0};
676 /* check if we have "<?xml" */
677 if (reader_cmp(reader, xmldeclW)) return S_FALSE;
679 reader_skipn(reader, 5);
680 hr = reader_parse_versioninfo(reader);
684 hr = reader_parse_encdecl(reader);
688 hr = reader_parse_sddecl(reader);
692 reader_skipspaces(reader);
693 if (reader_cmp(reader, declcloseW)) return WC_E_XMLDECL;
694 reader_skipn(reader, 2);
699 static HRESULT WINAPI xmlreader_QueryInterface(IXmlReader *iface, REFIID riid, void** ppvObject)
701 xmlreader *This = impl_from_IXmlReader(iface);
703 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
705 if (IsEqualGUID(riid, &IID_IUnknown) ||
706 IsEqualGUID(riid, &IID_IXmlReader))
712 FIXME("interface %s not implemented\n", debugstr_guid(riid));
713 return E_NOINTERFACE;
716 IXmlReader_AddRef(iface);
721 static ULONG WINAPI xmlreader_AddRef(IXmlReader *iface)
723 xmlreader *This = impl_from_IXmlReader(iface);
724 ULONG ref = InterlockedIncrement(&This->ref);
725 TRACE("(%p)->(%d)\n", This, ref);
729 static ULONG WINAPI xmlreader_Release(IXmlReader *iface)
731 xmlreader *This = impl_from_IXmlReader(iface);
732 LONG ref = InterlockedDecrement(&This->ref);
734 TRACE("(%p)->(%d)\n", This, ref);
738 IMalloc *imalloc = This->imalloc;
739 if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface);
740 reader_free(This, This);
741 if (imalloc) IMalloc_Release(imalloc);
747 static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input)
749 xmlreader *This = impl_from_IXmlReader(iface);
752 TRACE("(%p %p)\n", This, input);
756 readerinput_release_stream(This->input);
757 IUnknown_Release(&This->input->IXmlReaderInput_iface);
761 This->line = This->pos = 0;
763 /* just reset current input */
766 This->state = XmlReadState_Initial;
770 /* now try IXmlReaderInput, ISequentialStream, IStream */
771 hr = IUnknown_QueryInterface(input, &IID_IXmlReaderInput, (void**)&This->input);
774 IXmlReaderInput *readerinput;
776 /* create IXmlReaderInput basing on supplied interface */
777 hr = CreateXmlReaderInputWithEncodingName(input,
778 NULL, NULL, FALSE, NULL, &readerinput);
779 if (hr != S_OK) return hr;
780 This->input = impl_from_IXmlReaderInput(readerinput);
783 /* set stream for supplied IXmlReaderInput */
784 hr = readerinput_query_for_stream(This->input);
786 This->state = XmlReadState_Initial;
791 static HRESULT WINAPI xmlreader_GetProperty(IXmlReader* iface, UINT property, LONG_PTR *value)
793 xmlreader *This = impl_from_IXmlReader(iface);
795 TRACE("(%p %u %p)\n", This, property, value);
797 if (!value) return E_INVALIDARG;
801 case XmlReaderProperty_DtdProcessing:
802 *value = This->dtdmode;
804 case XmlReaderProperty_ReadState:
805 *value = This->state;
808 FIXME("Unimplemented property (%u)\n", property);
815 static HRESULT WINAPI xmlreader_SetProperty(IXmlReader* iface, UINT property, LONG_PTR value)
817 xmlreader *This = impl_from_IXmlReader(iface);
819 TRACE("(%p %u %lu)\n", iface, property, value);
823 case XmlReaderProperty_DtdProcessing:
824 if (value < 0 || value > _DtdProcessing_Last) return E_INVALIDARG;
825 This->dtdmode = value;
828 FIXME("Unimplemented property (%u)\n", property);
835 static HRESULT WINAPI xmlreader_Read(IXmlReader* iface, XmlNodeType *node_type)
837 xmlreader *This = impl_from_IXmlReader(iface);
839 FIXME("(%p)->(%p): stub\n", This, node_type);
841 if (This->state == XmlReadState_Closed) return S_FALSE;
843 /* if it's a first call for a new input we need to detect stream encoding */
844 if (This->state == XmlReadState_Initial)
849 hr = readerinput_growraw(This->input);
850 if (FAILED(hr)) return hr;
852 /* try to detect encoding by BOM or data and set input code page */
853 hr = readerinput_detectencoding(This->input, &enc);
854 TRACE("detected encoding %s, 0x%08x\n", debugstr_w(xml_encoding_map[enc].name), hr);
855 if (FAILED(hr)) return hr;
857 /* always switch first time cause we have to put something in */
858 readerinput_switchencoding(This->input, enc);
860 /* parse xml declaration */
861 hr = reader_parse_xmldecl(This);
862 if (FAILED(hr)) return hr;
866 This->state = XmlReadState_Interactive;
867 This->nodetype = *node_type = XmlNodeType_XmlDeclaration;
875 static HRESULT WINAPI xmlreader_GetNodeType(IXmlReader* iface, XmlNodeType *node_type)
877 xmlreader *This = impl_from_IXmlReader(iface);
878 TRACE("(%p)->(%p)\n", This, node_type);
879 *node_type = This->nodetype;
880 return This->state == XmlReadState_Closed ? S_FALSE : S_OK;
883 static HRESULT WINAPI xmlreader_MoveToFirstAttribute(IXmlReader* iface)
885 FIXME("(%p): stub\n", iface);
889 static HRESULT WINAPI xmlreader_MoveToNextAttribute(IXmlReader* iface)
891 FIXME("(%p): stub\n", iface);
895 static HRESULT WINAPI xmlreader_MoveToAttributeByName(IXmlReader* iface,
897 LPCWSTR namespaceUri)
899 FIXME("(%p %p %p): stub\n", iface, local_name, namespaceUri);
903 static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader* iface)
905 FIXME("(%p): stub\n", iface);
909 static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader* iface, LPCWSTR *qualifiedName,
910 UINT *qualifiedName_length)
912 FIXME("(%p %p %p): stub\n", iface, qualifiedName, qualifiedName_length);
916 static HRESULT WINAPI xmlreader_GetNamespaceUri(IXmlReader* iface,
917 LPCWSTR *namespaceUri,
918 UINT *namespaceUri_length)
920 FIXME("(%p %p %p): stub\n", iface, namespaceUri, namespaceUri_length);
924 static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader* iface,
926 UINT *local_name_length)
928 FIXME("(%p %p %p): stub\n", iface, local_name, local_name_length);
932 static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface,
936 FIXME("(%p %p %p): stub\n", iface, prefix, prefix_length);
940 static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface,
944 FIXME("(%p %p %p): stub\n", iface, value, value_length);
948 static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader* iface,
953 FIXME("(%p %p %u %p): stub\n", iface, buffer, chunk_size, read);
957 static HRESULT WINAPI xmlreader_GetBaseUri(IXmlReader* iface,
959 UINT *baseUri_length)
961 FIXME("(%p %p %p): stub\n", iface, baseUri, baseUri_length);
965 static BOOL WINAPI xmlreader_IsDefault(IXmlReader* iface)
967 FIXME("(%p): stub\n", iface);
971 static BOOL WINAPI xmlreader_IsEmptyElement(IXmlReader* iface)
973 FIXME("(%p): stub\n", iface);
977 static HRESULT WINAPI xmlreader_GetLineNumber(IXmlReader* iface, UINT *lineNumber)
979 xmlreader *This = impl_from_IXmlReader(iface);
981 TRACE("(%p %p)\n", This, lineNumber);
983 if (!lineNumber) return E_INVALIDARG;
985 *lineNumber = This->line;
990 static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *linePosition)
992 xmlreader *This = impl_from_IXmlReader(iface);
994 TRACE("(%p %p)\n", This, linePosition);
996 if (!linePosition) return E_INVALIDARG;
998 *linePosition = This->pos;
1003 static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader* iface, UINT *attributeCount)
1005 FIXME("(%p %p): stub\n", iface, attributeCount);
1009 static HRESULT WINAPI xmlreader_GetDepth(IXmlReader* iface, UINT *depth)
1011 FIXME("(%p %p): stub\n", iface, depth);
1015 static BOOL WINAPI xmlreader_IsEOF(IXmlReader* iface)
1017 FIXME("(%p): stub\n", iface);
1021 static const struct IXmlReaderVtbl xmlreader_vtbl =
1023 xmlreader_QueryInterface,
1027 xmlreader_GetProperty,
1028 xmlreader_SetProperty,
1030 xmlreader_GetNodeType,
1031 xmlreader_MoveToFirstAttribute,
1032 xmlreader_MoveToNextAttribute,
1033 xmlreader_MoveToAttributeByName,
1034 xmlreader_MoveToElement,
1035 xmlreader_GetQualifiedName,
1036 xmlreader_GetNamespaceUri,
1037 xmlreader_GetLocalName,
1038 xmlreader_GetPrefix,
1040 xmlreader_ReadValueChunk,
1041 xmlreader_GetBaseUri,
1042 xmlreader_IsDefault,
1043 xmlreader_IsEmptyElement,
1044 xmlreader_GetLineNumber,
1045 xmlreader_GetLinePosition,
1046 xmlreader_GetAttributeCount,
1051 /** IXmlReaderInput **/
1052 static HRESULT WINAPI xmlreaderinput_QueryInterface(IXmlReaderInput *iface, REFIID riid, void** ppvObject)
1054 xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
1056 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
1058 if (IsEqualGUID(riid, &IID_IXmlReaderInput) ||
1059 IsEqualGUID(riid, &IID_IUnknown))
1065 WARN("interface %s not implemented\n", debugstr_guid(riid));
1066 return E_NOINTERFACE;
1069 IUnknown_AddRef(iface);
1074 static ULONG WINAPI xmlreaderinput_AddRef(IXmlReaderInput *iface)
1076 xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
1077 ULONG ref = InterlockedIncrement(&This->ref);
1078 TRACE("(%p)->(%d)\n", This, ref);
1082 static ULONG WINAPI xmlreaderinput_Release(IXmlReaderInput *iface)
1084 xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
1085 LONG ref = InterlockedDecrement(&This->ref);
1087 TRACE("(%p)->(%d)\n", This, ref);
1091 IMalloc *imalloc = This->imalloc;
1092 if (This->input) IUnknown_Release(This->input);
1093 if (This->stream) ISequentialStream_Release(This->stream);
1094 if (This->buffer) free_input_buffer(This->buffer);
1095 readerinput_free(This, This->baseuri);
1096 readerinput_free(This, This);
1097 if (imalloc) IMalloc_Release(imalloc);
1103 static const struct IUnknownVtbl xmlreaderinput_vtbl =
1105 xmlreaderinput_QueryInterface,
1106 xmlreaderinput_AddRef,
1107 xmlreaderinput_Release
1110 HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
1114 TRACE("(%s, %p, %p)\n", wine_dbgstr_guid(riid), obj, imalloc);
1116 if (!IsEqualGUID(riid, &IID_IXmlReader))
1118 ERR("Unexpected IID requested -> (%s)\n", wine_dbgstr_guid(riid));
1123 reader = IMalloc_Alloc(imalloc, sizeof(*reader));
1125 reader = heap_alloc(sizeof(*reader));
1126 if(!reader) return E_OUTOFMEMORY;
1128 reader->IXmlReader_iface.lpVtbl = &xmlreader_vtbl;
1130 reader->input = NULL;
1131 reader->state = XmlReadState_Closed;
1132 reader->dtdmode = DtdProcessing_Prohibit;
1133 reader->line = reader->pos = 0;
1134 reader->imalloc = imalloc;
1135 if (imalloc) IMalloc_AddRef(imalloc);
1136 reader->nodetype = XmlNodeType_None;
1138 *obj = &reader->IXmlReader_iface;
1140 TRACE("returning iface %p\n", *obj);
1145 HRESULT WINAPI CreateXmlReaderInputWithEncodingName(IUnknown *stream,
1150 IXmlReaderInput **ppInput)
1152 xmlreaderinput *readerinput;
1155 TRACE("%p %p %s %d %s %p\n", stream, imalloc, wine_dbgstr_w(encoding),
1156 hint, wine_dbgstr_w(base_uri), ppInput);
1158 if (!stream || !ppInput) return E_INVALIDARG;
1161 readerinput = IMalloc_Alloc(imalloc, sizeof(*readerinput));
1163 readerinput = heap_alloc(sizeof(*readerinput));
1164 if(!readerinput) return E_OUTOFMEMORY;
1166 readerinput->IXmlReaderInput_iface.lpVtbl = &xmlreaderinput_vtbl;
1167 readerinput->ref = 1;
1168 readerinput->imalloc = imalloc;
1169 readerinput->stream = NULL;
1170 if (imalloc) IMalloc_AddRef(imalloc);
1171 readerinput->encoding = parse_encoding_name(encoding, -1);
1172 readerinput->hint = hint;
1173 readerinput->baseuri = readerinput_strdupW(readerinput, base_uri);
1175 hr = alloc_input_buffer(readerinput);
1178 readerinput_free(readerinput, readerinput);
1181 IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&readerinput->input);
1183 *ppInput = &readerinput->IXmlReaderInput_iface;
1185 TRACE("returning iface %p\n", *ppInput);