ReactOS  r76032
reader.c
Go to the documentation of this file.
1 /*
2  * IXmlReader implementation
3  *
4  * Copyright 2010, 2012-2013, 2016-2017 Nikolay Sivov
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include "xmllite_private.h"
22 
23 #include <stdio.h>
24 #include <assert.h>
25 
26 #include <wine/list.h>
27 #include <wine/unicode.h>
28 
29 /* not defined in public headers */
30 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
31 
32 typedef enum
33 {
41  XmlReadInState_MiscEnd, /* optional Misc at the end of a document */
44 
45 /* This state denotes where parsing was interrupted by input problem.
46  Reader resumes parsing using this information. */
47 typedef enum
48 {
58 
59 /* saved pointer index to resume from particular input position */
60 typedef enum
61 {
62  XmlReadResume_Name, /* PITarget, name for NCName, prefix for QName */
63  XmlReadResume_Local, /* local for QName */
64  XmlReadResume_Body, /* PI body, comment text, CDATA text, CharData text */
67 
68 typedef enum
69 {
76 
77 static const WCHAR usasciiW[] = {'U','S','-','A','S','C','I','I',0};
78 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
79 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
80 
81 static const WCHAR dblquoteW[] = {'\"',0};
82 static const WCHAR quoteW[] = {'\'',0};
83 static const WCHAR ltW[] = {'<',0};
84 static const WCHAR gtW[] = {'>',0};
85 static const WCHAR commentW[] = {'<','!','-','-',0};
86 static const WCHAR piW[] = {'<','?',0};
87 
88 static BOOL is_namestartchar(WCHAR ch);
89 
90 static const char *debugstr_nodetype(XmlNodeType nodetype)
91 {
92  static const char * const type_names[] =
93  {
94  "None",
95  "Element",
96  "Attribute",
97  "Text",
98  "CDATA",
99  "",
100  "",
101  "ProcessingInstruction",
102  "Comment",
103  "",
104  "DocumentType",
105  "",
106  "",
107  "Whitespace",
108  "",
109  "EndElement",
110  "",
111  "XmlDeclaration"
112  };
113 
114  if (nodetype > _XmlNodeType_Last)
115  return wine_dbg_sprintf("unknown type=%d", nodetype);
116 
117  return type_names[nodetype];
118 }
119 
120 static const char *debugstr_reader_prop(XmlReaderProperty prop)
121 {
122  static const char * const prop_names[] =
123  {
124  "MultiLanguage",
125  "ConformanceLevel",
126  "RandomAccess",
127  "XmlResolver",
128  "DtdProcessing",
129  "ReadState",
130  "MaxElementDepth",
131  "MaxEntityExpansion"
132  };
133 
134  if (prop > _XmlReaderProperty_Last)
135  return wine_dbg_sprintf("unknown property=%d", prop);
136 
137  return prop_names[prop];
138 }
139 
140 struct xml_encoding_data
141 {
142  const WCHAR *name;
144  UINT cp;
145 };
146 
147 static const struct xml_encoding_data xml_encoding_map[] = {
148  { usasciiW, XmlEncoding_USASCII, 20127 },
149  { utf16W, XmlEncoding_UTF16, 1200 },
151 };
152 
154 {
155  return xml_encoding_map[encoding].name;
156 }
157 
159 {
160  int i;
161  for (i = 0; i < sizeof(xml_encoding_map)/sizeof(xml_encoding_map[0]); i++)
162  {
163  if (xml_encoding_map[i].cp == codepage) return xml_encoding_map[i].enc;
164  }
165  return XmlEncoding_Unknown;
166 }
167 
168 typedef struct
169 {
170  char *data;
172  unsigned int allocated;
173  unsigned int written;
176 
177 typedef struct input_buffer input_buffer;
178 
179 typedef struct
180 {
183  /* reference passed on IXmlReaderInput creation, is kept when input is created */
189  /* stream reference set after SetInput() call from reader,
190  stored as sequential stream, cause currently
191  optimizations possible with IStream aren't implemented */
194  unsigned int pending : 1;
196 
197 static const struct IUnknownVtbl xmlreaderinputvtbl;
198 
199 /* Structure to hold parsed string of specific length.
200 
201  Reader stores node value as 'start' pointer, on request
202  a null-terminated version of it is allocated.
203 
204  To init a strval variable use reader_init_strval(),
205  to set strval as a reader value use reader_set_strval().
206  */
207 typedef struct
208 {
209  WCHAR *str; /* allocated null-terminated string */
210  UINT len; /* length in WCHARs, altered after ReadValueChunk */
211  UINT start; /* input position where value starts */
212 } strval;
213 
214 static WCHAR emptyW[] = {0};
215 static WCHAR xmlW[] = {'x','m','l',0};
216 static WCHAR xmlnsW[] = {'x','m','l','n','s',0};
217 static const strval strval_empty = { emptyW };
218 static const strval strval_xml = { xmlW, 3 };
219 static const strval strval_xmlns = { xmlnsW, 5 };
220 
222 {
225 };
226 
228 {
231 };
232 
233 struct attribute
234 {
235  struct list entry;
241  unsigned int flags;
242 };
243 
244 struct element
245 {
246  struct list entry;
251 };
252 
253 struct ns
254 {
255  struct list entry;
258  struct element *element;
259 };
260 
261 typedef struct
262 {
268  HRESULT error; /* error set on XmlReadState_Error */
275  struct reader_position position;
276  struct list attrs; /* attributes list for current node */
277  struct attribute *attr; /* current attribute */
279  struct list nsdef;
280  struct list ns;
281  struct list elements;
287  struct element empty_element; /* used for empty elements without end tag <a />,
288  and to keep <?xml reader position */
289  UINT resume[XmlReadResume_Last]; /* offsets used to resume reader */
290 } xmlreader;
291 
293 {
298 };
299 
301 {
302  return CONTAINING_RECORD(iface, xmlreader, IXmlReader_iface);
303 }
304 
306 {
307  return CONTAINING_RECORD(iface, xmlreaderinput, IXmlReaderInput_iface);
308 }
309 
310 /* reader memory allocation functions */
311 static inline void *reader_alloc(xmlreader *reader, size_t len)
312 {
313  return m_alloc(reader->imalloc, len);
314 }
315 
316 static inline void *reader_alloc_zero(xmlreader *reader, size_t len)
317 {
318  void *ret = reader_alloc(reader, len);
319  if (ret)
320  memset(ret, 0, len);
321  return ret;
322 }
323 
324 static inline void reader_free(xmlreader *reader, void *mem)
325 {
326  m_free(reader->imalloc, mem);
327 }
328 
329 /* Just return pointer from offset, no attempt to read more. */
331 {
332  encoded_buffer *buffer = &reader->input->buffer->utf16;
333  return (WCHAR*)buffer->data + offset;
334 }
335 
336 static inline WCHAR *reader_get_strptr(const xmlreader *reader, const strval *v)
337 {
338  return v->str ? v->str : reader_get_ptr2(reader, v->start);
339 }
340 
342 {
343  *dest = *src;
344 
345  if (src->str != strval_empty.str)
346  {
347  dest->str = reader_alloc(reader, (dest->len+1)*sizeof(WCHAR));
348  if (!dest->str) return E_OUTOFMEMORY;
349  memcpy(dest->str, reader_get_strptr(reader, src), dest->len*sizeof(WCHAR));
350  dest->str[dest->len] = 0;
351  dest->start = 0;
352  }
353 
354  return S_OK;
355 }
356 
357 /* reader input memory allocation functions */
358 static inline void *readerinput_alloc(xmlreaderinput *input, size_t len)
359 {
360  return m_alloc(input->imalloc, len);
361 }
362 
363 static inline void *readerinput_realloc(xmlreaderinput *input, void *mem, size_t len)
364 {
365  return m_realloc(input->imalloc, mem, len);
366 }
367 
368 static inline void readerinput_free(xmlreaderinput *input, void *mem)
369 {
370  m_free(input->imalloc, mem);
371 }
372 
374 {
375  LPWSTR ret = NULL;
376 
377  if(str) {
378  DWORD size;
379 
380  size = (strlenW(str)+1)*sizeof(WCHAR);
381  ret = readerinput_alloc(input, size);
382  if (ret) memcpy(ret, str, size);
383  }
384 
385  return ret;
386 }
387 
388 /* This one frees stored string value if needed */
390 {
391  if (v->str != strval_empty.str)
392  {
393  reader_free(reader, v->str);
394  *v = strval_empty;
395  }
396 }
397 
399 {
400  struct attribute *attr, *attr2;
401  LIST_FOR_EACH_ENTRY_SAFE(attr, attr2, &reader->attrs, struct attribute, entry)
402  {
403  reader_free_strvalued(reader, &attr->localname);
404  reader_free_strvalued(reader, &attr->value);
405  reader_free(reader, attr);
406  }
407  list_init(&reader->attrs);
408  reader->attr_count = 0;
409  reader->attr = NULL;
410 }
411 
412 /* attribute data holds pointers to buffer data, so buffer shrink is not possible
413  while we are on a node with attributes */
415  strval *value, const struct reader_position *position, unsigned int flags)
416 {
417  struct attribute *attr;
418  HRESULT hr;
419 
420  attr = reader_alloc(reader, sizeof(*attr));
421  if (!attr) return E_OUTOFMEMORY;
422 
423  hr = reader_strvaldup(reader, localname, &attr->localname);
424  if (hr == S_OK)
425  {
426  hr = reader_strvaldup(reader, value, &attr->value);
427  if (hr != S_OK)
428  reader_free_strvalued(reader, &attr->value);
429  }
430  if (hr != S_OK)
431  {
432  reader_free(reader, attr);
433  return hr;
434  }
435 
436  if (prefix)
437  attr->prefix = *prefix;
438  else
439  memset(&attr->prefix, 0, sizeof(attr->prefix));
440  attr->qname = qname ? *qname : *localname;
441  attr->position = *position;
442  attr->flags = flags;
443  list_add_tail(&reader->attrs, &attr->entry);
444  reader->attr_count++;
445 
446  return S_OK;
447 }
448 
449 /* Returns current element, doesn't check if reader is actually positioned on it. */
451 {
452  if (reader->is_empty_element)
453  return &reader->empty_element;
454 
455  return LIST_ENTRY(list_head(&reader->elements), struct element, entry);
456 }
457 
459 {
460  v->start = start;
461  v->len = len;
462  v->str = NULL;
463 }
464 
465 static inline const char* debug_strval(const xmlreader *reader, const strval *v)
466 {
467  return debugstr_wn(reader_get_strptr(reader, v), v->len);
468 }
469 
470 /* used to initialize from constant string */
471 static inline void reader_init_cstrvalue(WCHAR *str, UINT len, strval *v)
472 {
473  v->start = 0;
474  v->len = len;
475  v->str = str;
476 }
477 
479 {
480  reader_free_strvalued(reader, &reader->strvalues[type]);
481 }
482 
484 {
485  int type;
486  for (type = 0; type < StringValue_Last; type++)
487  reader_free_strvalue(reader, type);
488 }
489 
490 /* This helper should only be used to test if strings are the same,
491  it doesn't try to sort. */
492 static inline int strval_eq(const xmlreader *reader, const strval *str1, const strval *str2)
493 {
494  if (str1->len != str2->len) return 0;
495  return !memcmp(reader_get_strptr(reader, str1), reader_get_strptr(reader, str2), str1->len*sizeof(WCHAR));
496 }
497 
499 {
500  struct element *elem, *elem2;
501  LIST_FOR_EACH_ENTRY_SAFE(elem, elem2, &reader->elements, struct element, entry)
502  {
503  reader_free_strvalued(reader, &elem->prefix);
504  reader_free_strvalued(reader, &elem->localname);
505  reader_free_strvalued(reader, &elem->qname);
506  reader_free(reader, elem);
507  }
508  list_init(&reader->elements);
509  reader_free_strvalued(reader, &reader->empty_element.localname);
510  reader_free_strvalued(reader, &reader->empty_element.qname);
511  reader->is_empty_element = FALSE;
512 }
513 
515 {
516  struct list *nslist = prefix ? &reader->ns : &reader->nsdef;
517  struct ns *ns;
518 
519  LIST_FOR_EACH_ENTRY_REV(ns, nslist, struct ns, entry) {
520  if (strval_eq(reader, prefix, &ns->prefix))
521  return ns;
522  }
523 
524  return NULL;
525 }
526 
528 {
529  return (++reader->depth >= reader->max_depth && reader->max_depth) ? SC_E_MAXELEMENTDEPTH : S_OK;
530 }
531 
533 {
534  if (reader->depth)
535  reader->depth--;
536 }
537 
539 {
540  struct ns *ns;
541  HRESULT hr;
542 
543  ns = reader_alloc(reader, sizeof(*ns));
544  if (!ns) return E_OUTOFMEMORY;
545 
546  if (def)
547  memset(&ns->prefix, 0, sizeof(ns->prefix));
548  else {
549  hr = reader_strvaldup(reader, prefix, &ns->prefix);
550  if (FAILED(hr)) {
551  reader_free(reader, ns);
552  return hr;
553  }
554  }
555 
556  hr = reader_strvaldup(reader, uri, &ns->uri);
557  if (FAILED(hr)) {
558  reader_free_strvalued(reader, &ns->prefix);
559  reader_free(reader, ns);
560  return hr;
561  }
562 
563  ns->element = NULL;
564  list_add_head(def ? &reader->nsdef : &reader->ns, &ns->entry);
565  return hr;
566 }
567 
569 {
570  reader_free_strvalued(reader, &element->prefix);
571  reader_free_strvalued(reader, &element->localname);
572  reader_free_strvalued(reader, &element->qname);
573  reader_free(reader, element);
574 }
575 
577 {
578  struct ns *ns;
579 
580  LIST_FOR_EACH_ENTRY(ns, &reader->ns, struct ns, entry) {
581  if (ns->element)
582  break;
583  ns->element = element;
584  }
585 
586  LIST_FOR_EACH_ENTRY(ns, &reader->nsdef, struct ns, entry) {
587  if (ns->element)
588  break;
589  ns->element = element;
590  }
591 }
592 
594  strval *qname, const struct reader_position *position)
595 {
596  struct element *element;
597  HRESULT hr;
598 
599  element = reader_alloc_zero(reader, sizeof(*element));
600  if (!element)
601  return E_OUTOFMEMORY;
602 
603  if ((hr = reader_strvaldup(reader, prefix, &element->prefix)) == S_OK &&
604  (hr = reader_strvaldup(reader, localname, &element->localname)) == S_OK &&
605  (hr = reader_strvaldup(reader, qname, &element->qname)) == S_OK)
606  {
607  list_add_head(&reader->elements, &element->entry);
608  reader_mark_ns_nodes(reader, element);
609  reader->is_empty_element = FALSE;
610  element->position = *position;
611  }
612  else
613  reader_free_element(reader, element);
614 
615  return hr;
616 }
617 
619 {
620  struct ns *ns, *ns2;
621 
622  LIST_FOR_EACH_ENTRY_SAFE_REV(ns, ns2, &reader->ns, struct ns, entry) {
623  if (ns->element != element)
624  break;
625 
626  list_remove(&ns->entry);
627  reader_free_strvalued(reader, &ns->prefix);
628  reader_free_strvalued(reader, &ns->uri);
629  reader_free(reader, ns);
630  }
631 
632  if (!list_empty(&reader->nsdef)) {
633  ns = LIST_ENTRY(list_head(&reader->nsdef), struct ns, entry);
634  if (ns->element == element) {
635  list_remove(&ns->entry);
636  reader_free_strvalued(reader, &ns->prefix);
637  reader_free_strvalued(reader, &ns->uri);
638  reader_free(reader, ns);
639  }
640  }
641 }
642 
644 {
645  struct element *element;
646 
647  if (list_empty(&reader->elements))
648  return;
649 
650  element = LIST_ENTRY(list_head(&reader->elements), struct element, entry);
651  list_remove(&element->entry);
652 
653  reader_pop_ns_nodes(reader, element);
654  reader_free_element(reader, element);
655 
656  /* It was a root element, the rest is expected as Misc */
657  if (list_empty(&reader->elements))
659 }
660 
661 /* Always make a copy, cause strings are supposed to be null terminated. Null pointer for 'value'
662  means node value is to be determined. */
664 {
665  strval *v = &reader->strvalues[type];
666 
667  reader_free_strvalue(reader, type);
668  if (!value)
669  {
670  v->str = NULL;
671  v->start = 0;
672  v->len = 0;
673  return;
674  }
675 
676  if (value->str == strval_empty.str)
677  *v = *value;
678  else
679  {
680  if (type == StringValue_Value)
681  {
682  /* defer allocation for value string */
683  v->str = NULL;
684  v->start = value->start;
685  v->len = value->len;
686  }
687  else
688  {
689  v->str = reader_alloc(reader, (value->len + 1)*sizeof(WCHAR));
690  memcpy(v->str, reader_get_strptr(reader, value), value->len*sizeof(WCHAR));
691  v->str[value->len] = 0;
692  v->len = value->len;
693  }
694  }
695 }
696 
697 static inline int is_reader_pending(xmlreader *reader)
698 {
699  return reader->input->pending;
700 }
701 
703 {
704  const int initial_len = 0x2000;
705  buffer->data = readerinput_alloc(input, initial_len);
706  if (!buffer->data) return E_OUTOFMEMORY;
707 
708  memset(buffer->data, 0, 4);
709  buffer->cur = 0;
710  buffer->allocated = initial_len;
711  buffer->written = 0;
712  buffer->prev_cr = FALSE;
713 
714  return S_OK;
715 }
716 
718 {
719  readerinput_free(input, buffer->data);
720 }
721 
723 {
724  if (encoding == XmlEncoding_Unknown)
725  {
726  FIXME("unsupported encoding %d\n", encoding);
727  return E_NOTIMPL;
728  }
729 
730  *cp = xml_encoding_map[encoding].cp;
731 
732  return S_OK;
733 }
734 
736 {
737  int min, max, n, c;
738 
739  if (!name) return XmlEncoding_Unknown;
740 
741  min = 0;
742  max = sizeof(xml_encoding_map)/sizeof(xml_encoding_map[0]) - 1;
743 
744  while (min <= max)
745  {
746  n = (min+max)/2;
747 
748  if (len != -1)
749  c = strncmpiW(xml_encoding_map[n].name, name, len);
750  else
751  c = strcmpiW(xml_encoding_map[n].name, name);
752  if (!c)
753  return xml_encoding_map[n].enc;
754 
755  if (c > 0)
756  max = n-1;
757  else
758  min = n+1;
759  }
760 
761  return XmlEncoding_Unknown;
762 }
763 
765 {
767  HRESULT hr;
768 
769  input->buffer = NULL;
770 
771  buffer = readerinput_alloc(input, sizeof(*buffer));
772  if (!buffer) return E_OUTOFMEMORY;
773 
774  buffer->input = input;
775  buffer->code_page = ~0; /* code page is unknown at this point */
776  hr = init_encoded_buffer(input, &buffer->utf16);
777  if (hr != S_OK) {
778  readerinput_free(input, buffer);
779  return hr;
780  }
781 
782  hr = init_encoded_buffer(input, &buffer->encoded);
783  if (hr != S_OK) {
784  free_encoded_buffer(input, &buffer->utf16);
785  readerinput_free(input, buffer);
786  return hr;
787  }
788 
789  input->buffer = buffer;
790  return S_OK;
791 }
792 
794 {
795  free_encoded_buffer(buffer->input, &buffer->encoded);
796  free_encoded_buffer(buffer->input, &buffer->utf16);
797  readerinput_free(buffer->input, buffer);
798 }
799 
801 {
802  if (readerinput->stream) {
803  ISequentialStream_Release(readerinput->stream);
804  readerinput->stream = NULL;
805  }
806 }
807 
808 /* Queries already stored interface for IStream/ISequentialStream.
809  Interface supplied on creation will be overwritten */
811 {
812  HRESULT hr;
813 
814  readerinput_release_stream(readerinput);
815  hr = IUnknown_QueryInterface(readerinput->input, &IID_IStream, (void**)&readerinput->stream);
816  if (hr != S_OK)
817  hr = IUnknown_QueryInterface(readerinput->input, &IID_ISequentialStream, (void**)&readerinput->stream);
818 
819  return hr;
820 }
821 
822 /* reads a chunk to raw buffer */
824 {
825  encoded_buffer *buffer = &readerinput->buffer->encoded;
826  /* to make sure aligned length won't exceed allocated length */
827  ULONG len = buffer->allocated - buffer->written - 4;
828  ULONG read;
829  HRESULT hr;
830 
831  /* always try to get aligned to 4 bytes, so the only case we can get partially read characters is
832  variable width encodings like UTF-8 */
833  len = (len + 3) & ~3;
834  /* try to use allocated space or grow */
835  if (buffer->allocated - buffer->written < len)
836  {
837  buffer->allocated *= 2;
838  buffer->data = readerinput_realloc(readerinput, buffer->data, buffer->allocated);
839  len = buffer->allocated - buffer->written;
840  }
841 
842  read = 0;
843  hr = ISequentialStream_Read(readerinput->stream, buffer->data + buffer->written, len, &read);
844  TRACE("written=%d, alloc=%d, requested=%d, read=%d, ret=0x%08x\n", buffer->written, buffer->allocated, len, read, hr);
845  readerinput->pending = hr == E_PENDING;
846  if (FAILED(hr)) return hr;
847  buffer->written += read;
848 
849  return hr;
850 }
851 
852 /* grows UTF-16 buffer so it has at least 'length' WCHAR chars free on return */
853 static void readerinput_grow(xmlreaderinput *readerinput, int length)
854 {
855  encoded_buffer *buffer = &readerinput->buffer->utf16;
856 
857  length *= sizeof(WCHAR);
858  /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
859  if (buffer->allocated < buffer->written + length + 4)
860  {
861  int grown_size = max(2*buffer->allocated, buffer->allocated + length);
862  buffer->data = readerinput_realloc(readerinput, buffer->data, grown_size);
863  buffer->allocated = grown_size;
864  }
865 }
866 
867 static inline BOOL readerinput_is_utf8(xmlreaderinput *readerinput)
868 {
869  static const char startA[] = {'<','?'};
870  static const char commentA[] = {'<','!'};
871  encoded_buffer *buffer = &readerinput->buffer->encoded;
872  unsigned char *ptr = (unsigned char*)buffer->data;
873 
874  return !memcmp(buffer->data, startA, sizeof(startA)) ||
875  !memcmp(buffer->data, commentA, sizeof(commentA)) ||
876  /* test start byte */
877  (ptr[0] == '<' &&
878  (
879  (ptr[1] && (ptr[1] <= 0x7f)) ||
880  (buffer->data[1] >> 5) == 0x6 || /* 2 bytes */
881  (buffer->data[1] >> 4) == 0xe || /* 3 bytes */
882  (buffer->data[1] >> 3) == 0x1e) /* 4 bytes */
883  );
884 }
885 
887 {
888  encoded_buffer *buffer = &readerinput->buffer->encoded;
889  static const char utf8bom[] = {0xef,0xbb,0xbf};
890  static const char utf16lebom[] = {0xff,0xfe};
891  WCHAR *ptrW;
892 
893  *enc = XmlEncoding_Unknown;
894 
895  if (buffer->written <= 3)
896  {
897  HRESULT hr = readerinput_growraw(readerinput);
898  if (FAILED(hr)) return hr;
899  if (buffer->written < 3) return MX_E_INPUTEND;
900  }
901 
902  ptrW = (WCHAR *)buffer->data;
903  /* try start symbols if we have enough data to do that, input buffer should contain
904  first chunk already */
905  if (readerinput_is_utf8(readerinput))
906  *enc = XmlEncoding_UTF8;
907  else if (*ptrW == '<')
908  {
909  ptrW++;
910  if (*ptrW == '?' || *ptrW == '!' || is_namestartchar(*ptrW))
911  *enc = XmlEncoding_UTF16;
912  }
913  /* try with BOM now */
914  else if (!memcmp(buffer->data, utf8bom, sizeof(utf8bom)))
915  {
916  buffer->cur += sizeof(utf8bom);
917  *enc = XmlEncoding_UTF8;
918  }
919  else if (!memcmp(buffer->data, utf16lebom, sizeof(utf16lebom)))
920  {
921  buffer->cur += sizeof(utf16lebom);
922  *enc = XmlEncoding_UTF16;
923  }
924 
925  return S_OK;
926 }
927 
929 {
930  encoded_buffer *buffer = &readerinput->buffer->encoded;
931  int len = buffer->written;
932 
933  /* complete single byte char */
934  if (!(buffer->data[len-1] & 0x80)) return len;
935 
936  /* find start byte of multibyte char */
937  while (--len && !(buffer->data[len] & 0xc0))
938  ;
939 
940  return len;
941 }
942 
943 /* Returns byte length of complete char sequence for buffer code page,
944  it's relative to current buffer position which is currently used for BOM handling
945  only. */
946 static int readerinput_get_convlen(xmlreaderinput *readerinput)
947 {
948  encoded_buffer *buffer = &readerinput->buffer->encoded;
949  int len;
950 
951  if (readerinput->buffer->code_page == CP_UTF8)
952  len = readerinput_get_utf8_convlen(readerinput);
953  else
954  len = buffer->written;
955 
956  TRACE("%d\n", len - buffer->cur);
957  return len - buffer->cur;
958 }
959 
960 /* It's possible that raw buffer has some leftovers from last conversion - some char
961  sequence that doesn't represent a full code point. Length argument should be calculated with
962  readerinput_get_convlen(), if it's -1 it will be calculated here. */
963 static void readerinput_shrinkraw(xmlreaderinput *readerinput, int len)
964 {
965  encoded_buffer *buffer = &readerinput->buffer->encoded;
966 
967  if (len == -1)
968  len = readerinput_get_convlen(readerinput);
969 
970  memmove(buffer->data, buffer->data + buffer->cur + (buffer->written - len), len);
971  /* everything below cur is lost too */
972  buffer->written -= len + buffer->cur;
973  /* after this point we don't need cur offset really,
974  it's used only to mark where actual data begins when first chunk is read */
975  buffer->cur = 0;
976 }
977 
979 {
980  BOOL prev_cr = buffer->prev_cr;
981  const WCHAR *src;
982  WCHAR *dest;
983 
984  src = dest = (WCHAR*)buffer->data + off;
985  while ((const char*)src < buffer->data + buffer->written)
986  {
987  if (*src == '\r')
988  {
989  *dest++ = '\n';
990  src++;
991  prev_cr = TRUE;
992  continue;
993  }
994  if(prev_cr && *src == '\n')
995  src++;
996  else
997  *dest++ = *src++;
998  prev_cr = FALSE;
999  }
1000 
1001  buffer->written = (char*)dest - buffer->data;
1002  buffer->prev_cr = prev_cr;
1003  *dest = 0;
1004 }
1005 
1006 /* note that raw buffer content is kept */
1008 {
1009  encoded_buffer *src = &readerinput->buffer->encoded;
1010  encoded_buffer *dest = &readerinput->buffer->utf16;
1011  int len, dest_len;
1012  HRESULT hr;
1013  WCHAR *ptr;
1014  UINT cp;
1015 
1016  hr = get_code_page(enc, &cp);
1017  if (FAILED(hr)) return;
1018 
1019  readerinput->buffer->code_page = cp;
1020  len = readerinput_get_convlen(readerinput);
1021 
1022  TRACE("switching to cp %d\n", cp);
1023 
1024  /* just copy in this case */
1025  if (enc == XmlEncoding_UTF16)
1026  {
1027  readerinput_grow(readerinput, len);
1028  memcpy(dest->data, src->data + src->cur, len);
1029  dest->written += len*sizeof(WCHAR);
1030  }
1031  else
1032  {
1033  dest_len = MultiByteToWideChar(cp, 0, src->data + src->cur, len, NULL, 0);
1034  readerinput_grow(readerinput, dest_len);
1035  ptr = (WCHAR*)dest->data;
1036  MultiByteToWideChar(cp, 0, src->data + src->cur, len, ptr, dest_len);
1037  ptr[dest_len] = 0;
1038  dest->written += dest_len*sizeof(WCHAR);
1039  }
1040 
1041  fixup_buffer_cr(dest, 0);
1042 }
1043 
1044 /* shrinks parsed data a buffer begins with */
1046 {
1047  encoded_buffer *buffer = &reader->input->buffer->utf16;
1048 
1049  /* avoid to move too often using threshold shrink length */
1050  if (buffer->cur*sizeof(WCHAR) > buffer->written / 2)
1051  {
1052  buffer->written -= buffer->cur*sizeof(WCHAR);
1053  memmove(buffer->data, (WCHAR*)buffer->data + buffer->cur, buffer->written);
1054  buffer->cur = 0;
1055  *(WCHAR*)&buffer->data[buffer->written] = 0;
1056  }
1057 }
1058 
1059 /* This is a normal way for reader to get new data converted from raw buffer to utf16 buffer.
1060  It won't attempt to shrink but will grow destination buffer if needed */
1062 {
1063  xmlreaderinput *readerinput = reader->input;
1064  encoded_buffer *src = &readerinput->buffer->encoded;
1065  encoded_buffer *dest = &readerinput->buffer->utf16;
1066  UINT cp = readerinput->buffer->code_page;
1067  int len, dest_len, prev_len;
1068  HRESULT hr;
1069  WCHAR *ptr;
1070 
1071  /* get some raw data from stream first */
1072  hr = readerinput_growraw(readerinput);
1073  len = readerinput_get_convlen(readerinput);
1074  prev_len = dest->written / sizeof(WCHAR);
1075 
1076  /* just copy for UTF-16 case */
1077  if (cp == 1200)
1078  {
1079  readerinput_grow(readerinput, len);
1080  memcpy(dest->data + dest->written, src->data + src->cur, len);
1081  dest->written += len*sizeof(WCHAR);
1082  }
1083  else
1084  {
1085  dest_len = MultiByteToWideChar(cp, 0, src->data + src->cur, len, NULL, 0);
1086  readerinput_grow(readerinput, dest_len);
1087  ptr = (WCHAR*)(dest->data + dest->written);
1088  MultiByteToWideChar(cp, 0, src->data + src->cur, len, ptr, dest_len);
1089  ptr[dest_len] = 0;
1090  dest->written += dest_len*sizeof(WCHAR);
1091  /* get rid of processed data */
1092  readerinput_shrinkraw(readerinput, len);
1093  }
1094 
1095  fixup_buffer_cr(dest, prev_len);
1096  return hr;
1097 }
1098 
1100 {
1101  return reader->input->buffer->utf16.cur;
1102 }
1103 
1105 {
1106  encoded_buffer *buffer = &reader->input->buffer->utf16;
1107  WCHAR *ptr = (WCHAR*)buffer->data + buffer->cur;
1108  if (!*ptr) reader_more(reader);
1109  return (WCHAR*)buffer->data + buffer->cur;
1110 }
1111 
1112 static int reader_cmp(xmlreader *reader, const WCHAR *str)
1113 {
1114  int i=0;
1115  const WCHAR *ptr = reader_get_ptr(reader);
1116  while (str[i])
1117  {
1118  if (!ptr[i])
1119  {
1120  reader_more(reader);
1121  ptr = reader_get_ptr(reader);
1122  }
1123  if (str[i] != ptr[i])
1124  return ptr[i] - str[i];
1125  i++;
1126  }
1127  return 0;
1128 }
1129 
1131 {
1132  if (ch == '\r')
1133  reader->position.line_position = 1;
1134  else if (ch == '\n')
1135  {
1136  reader->position.line_number++;
1137  reader->position.line_position = 1;
1138  }
1139  else
1140  reader->position.line_position++;
1141 }
1142 
1143 /* moves cursor n WCHARs forward */
1144 static void reader_skipn(xmlreader *reader, int n)
1145 {
1146  encoded_buffer *buffer = &reader->input->buffer->utf16;
1147  const WCHAR *ptr;
1148 
1149  while (*(ptr = reader_get_ptr(reader)) && n--)
1150  {
1151  reader_update_position(reader, *ptr);
1152  buffer->cur++;
1153  }
1154 }
1155 
1156 static inline BOOL is_wchar_space(WCHAR ch)
1157 {
1158  return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
1159 }
1160 
1161 /* [3] S ::= (#x20 | #x9 | #xD | #xA)+ */
1163 {
1164  const WCHAR *ptr = reader_get_ptr(reader);
1165  UINT start = reader_get_cur(reader);
1166 
1167  while (is_wchar_space(*ptr))
1168  {
1169  reader_skipn(reader, 1);
1170  ptr = reader_get_ptr(reader);
1171  }
1172 
1173  return reader_get_cur(reader) - start;
1174 }
1175 
1176 /* [26] VersionNum ::= '1.' [0-9]+ */
1178 {
1179  static const WCHAR onedotW[] = {'1','.',0};
1180  WCHAR *ptr, *ptr2;
1181  UINT start;
1182 
1183  if (reader_cmp(reader, onedotW)) return WC_E_XMLDECL;
1184 
1185  start = reader_get_cur(reader);
1186  /* skip "1." */
1187  reader_skipn(reader, 2);
1188 
1189  ptr2 = ptr = reader_get_ptr(reader);
1190  while (*ptr >= '0' && *ptr <= '9')
1191  {
1192  reader_skipn(reader, 1);
1193  ptr = reader_get_ptr(reader);
1194  }
1195 
1196  if (ptr2 == ptr) return WC_E_DIGIT;
1197  reader_init_strvalue(start, reader_get_cur(reader)-start, val);
1198  TRACE("version=%s\n", debug_strval(reader, val));
1199  return S_OK;
1200 }
1201 
1202 /* [25] Eq ::= S? '=' S? */
1204 {
1205  static const WCHAR eqW[] = {'=',0};
1206  reader_skipspaces(reader);
1207  if (reader_cmp(reader, eqW)) return WC_E_EQUAL;
1208  /* skip '=' */
1209  reader_skipn(reader, 1);
1210  reader_skipspaces(reader);
1211  return S_OK;
1212 }
1213 
1214 /* [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') */
1216 {
1217  static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
1218  struct reader_position position;
1219  strval val, name;
1220  HRESULT hr;
1221 
1222  if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
1223 
1224  position = reader->position;
1225  if (reader_cmp(reader, versionW)) return WC_E_XMLDECL;
1226  reader_init_strvalue(reader_get_cur(reader), 7, &name);
1227  /* skip 'version' */
1228  reader_skipn(reader, 7);
1229 
1230  hr = reader_parse_eq(reader);
1231  if (FAILED(hr)) return hr;
1232 
1233  if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
1234  return WC_E_QUOTE;
1235  /* skip "'"|'"' */
1236  reader_skipn(reader, 1);
1237 
1238  hr = reader_parse_versionnum(reader, &val);
1239  if (FAILED(hr)) return hr;
1240 
1241  if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
1242  return WC_E_QUOTE;
1243 
1244  /* skip "'"|'"' */
1245  reader_skipn(reader, 1);
1246 
1247  return reader_add_attr(reader, NULL, &name, NULL, &val, &position, 0);
1248 }
1249 
1250 /* ([A-Za-z0-9._] | '-') */
1251 static inline BOOL is_wchar_encname(WCHAR ch)
1252 {
1253  return ((ch >= 'A' && ch <= 'Z') ||
1254  (ch >= 'a' && ch <= 'z') ||
1255  (ch >= '0' && ch <= '9') ||
1256  (ch == '.') || (ch == '_') ||
1257  (ch == '-'));
1258 }
1259 
1260 /* [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* */
1262 {
1263  WCHAR *start = reader_get_ptr(reader), *ptr;
1264  xml_encoding enc;
1265  int len;
1266 
1267  if ((*start < 'A' || *start > 'Z') && (*start < 'a' || *start > 'z'))
1268  return WC_E_ENCNAME;
1269 
1270  val->start = reader_get_cur(reader);
1271 
1272  ptr = start;
1273  while (is_wchar_encname(*++ptr))
1274  ;
1275 
1276  len = ptr - start;
1277  enc = parse_encoding_name(start, len);
1278  TRACE("encoding name %s\n", debugstr_wn(start, len));
1279  val->str = start;
1280  val->len = len;
1281 
1282  if (enc == XmlEncoding_Unknown)
1283  return WC_E_ENCNAME;
1284 
1285  /* skip encoding name */
1286  reader_skipn(reader, len);
1287  return S_OK;
1288 }
1289 
1290 /* [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ) */
1292 {
1293  static const WCHAR encodingW[] = {'e','n','c','o','d','i','n','g',0};
1294  struct reader_position position;
1295  strval name, val;
1296  HRESULT hr;
1297 
1298  if (!reader_skipspaces(reader)) return S_FALSE;
1299 
1300  position = reader->position;
1301  if (reader_cmp(reader, encodingW)) return S_FALSE;
1302  name.str = reader_get_ptr(reader);
1303  name.start = reader_get_cur(reader);
1304  name.len = 8;
1305  /* skip 'encoding' */
1306  reader_skipn(reader, 8);
1307 
1308  hr = reader_parse_eq(reader);
1309  if (FAILED(hr)) return hr;
1310 
1311  if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
1312  return WC_E_QUOTE;
1313  /* skip "'"|'"' */
1314  reader_skipn(reader, 1);
1315 
1316  hr = reader_parse_encname(reader, &val);
1317  if (FAILED(hr)) return hr;
1318 
1319  if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
1320  return WC_E_QUOTE;
1321 
1322  /* skip "'"|'"' */
1323  reader_skipn(reader, 1);
1324 
1325  return reader_add_attr(reader, NULL, &name, NULL, &val, &position, 0);
1326 }
1327 
1328 /* [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) */
1330 {
1331  static const WCHAR standaloneW[] = {'s','t','a','n','d','a','l','o','n','e',0};
1332  static const WCHAR yesW[] = {'y','e','s',0};
1333  static const WCHAR noW[] = {'n','o',0};
1334  struct reader_position position;
1335  strval name, val;
1336  UINT start;
1337  HRESULT hr;
1338 
1339  if (!reader_skipspaces(reader)) return S_FALSE;
1340 
1341  position = reader->position;
1342  if (reader_cmp(reader, standaloneW)) return S_FALSE;
1343  reader_init_strvalue(reader_get_cur(reader), 10, &name);
1344  /* skip 'standalone' */
1345  reader_skipn(reader, 10);
1346 
1347  hr = reader_parse_eq(reader);
1348  if (FAILED(hr)) return hr;
1349 
1350  if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
1351  return WC_E_QUOTE;
1352  /* skip "'"|'"' */
1353  reader_skipn(reader, 1);
1354 
1355  if (reader_cmp(reader, yesW) && reader_cmp(reader, noW))
1356  return WC_E_XMLDECL;
1357 
1358  start = reader_get_cur(reader);
1359  /* skip 'yes'|'no' */
1360  reader_skipn(reader, reader_cmp(reader, yesW) ? 2 : 3);
1361  reader_init_strvalue(start, reader_get_cur(reader)-start, &val);
1362  TRACE("standalone=%s\n", debug_strval(reader, &val));
1363 
1364  if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
1365  return WC_E_QUOTE;
1366  /* skip "'"|'"' */
1367  reader_skipn(reader, 1);
1368 
1369  return reader_add_attr(reader, NULL, &name, NULL, &val, &position, 0);
1370 }
1371 
1372 /* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
1374 {
1375  static const WCHAR xmldeclW[] = {'<','?','x','m','l',' ',0};
1376  static const WCHAR declcloseW[] = {'?','>',0};
1377  struct reader_position position;
1378  HRESULT hr;
1379 
1380  /* check if we have "<?xml " */
1381  if (reader_cmp(reader, xmldeclW))
1382  return S_FALSE;
1383 
1384  reader_skipn(reader, 2);
1385  position = reader->position;
1386  reader_skipn(reader, 3);
1387  hr = reader_parse_versioninfo(reader);
1388  if (FAILED(hr))
1389  return hr;
1390 
1391  hr = reader_parse_encdecl(reader);
1392  if (FAILED(hr))
1393  return hr;
1394 
1395  hr = reader_parse_sddecl(reader);
1396  if (FAILED(hr))
1397  return hr;
1398 
1399  reader_skipspaces(reader);
1400  if (reader_cmp(reader, declcloseW))
1401  return WC_E_XMLDECL;
1402 
1403  /* skip '?>' */
1404  reader_skipn(reader, 2);
1405 
1407  reader->empty_element.position = position;
1408  reader_set_strvalue(reader, StringValue_LocalName, &strval_xml);
1409  reader_set_strvalue(reader, StringValue_QualifiedName, &strval_xml);
1410 
1411  return S_OK;
1412 }
1413 
1414 /* [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->' */
1416 {
1417  WCHAR *ptr;
1418  UINT start;
1419 
1420  if (reader->resumestate == XmlReadResumeState_Comment)
1421  {
1422  start = reader->resume[XmlReadResume_Body];
1423  ptr = reader_get_ptr(reader);
1424  }
1425  else
1426  {
1427  /* skip '<!--' */
1428  reader_skipn(reader, 4);
1429  reader_shrink(reader);
1430  ptr = reader_get_ptr(reader);
1431  start = reader_get_cur(reader);
1432  reader->nodetype = XmlNodeType_Comment;
1433  reader->resume[XmlReadResume_Body] = start;
1436  }
1437 
1438  /* will exit when there's no more data, it won't attempt to
1439  read more from stream */
1440  while (*ptr)
1441  {
1442  if (ptr[0] == '-')
1443  {
1444  if (ptr[1] == '-')
1445  {
1446  if (ptr[2] == '>')
1447  {
1448  strval value;
1449 
1450  reader_init_strvalue(start, reader_get_cur(reader)-start, &value);
1451  TRACE("%s\n", debug_strval(reader, &value));
1452 
1453  /* skip rest of markup '->' */
1454  reader_skipn(reader, 3);
1455 
1456  reader_set_strvalue(reader, StringValue_Value, &value);
1457  reader->resume[XmlReadResume_Body] = 0;
1459  return S_OK;
1460  }
1461  else
1462  return WC_E_COMMENT;
1463  }
1464  }
1465 
1466  reader_skipn(reader, 1);
1467  ptr++;
1468  }
1469 
1470  return S_OK;
1471 }
1472 
1473 /* [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] */
1474 static inline BOOL is_char(WCHAR ch)
1475 {
1476  return (ch == '\t') || (ch == '\r') || (ch == '\n') ||
1477  (ch >= 0x20 && ch <= 0xd7ff) ||
1478  (ch >= 0xd800 && ch <= 0xdbff) || /* high surrogate */
1479  (ch >= 0xdc00 && ch <= 0xdfff) || /* low surrogate */
1480  (ch >= 0xe000 && ch <= 0xfffd);
1481 }
1482 
1483 /* [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] */
1484 static inline BOOL is_pubchar(WCHAR ch)
1485 {
1486  return (ch == ' ') ||
1487  (ch >= 'a' && ch <= 'z') ||
1488  (ch >= 'A' && ch <= 'Z') ||
1489  (ch >= '0' && ch <= '9') ||
1490  (ch >= '-' && ch <= ';') || /* '()*+,-./:; */
1491  (ch == '=') || (ch == '?') ||
1492  (ch == '@') || (ch == '!') ||
1493  (ch >= '#' && ch <= '%') || /* #$% */
1494  (ch == '_') || (ch == '\r') || (ch == '\n');
1495 }
1496 
1497 static inline BOOL is_namestartchar(WCHAR ch)
1498 {
1499  return (ch == ':') || (ch >= 'A' && ch <= 'Z') ||
1500  (ch == '_') || (ch >= 'a' && ch <= 'z') ||
1501  (ch >= 0xc0 && ch <= 0xd6) ||
1502  (ch >= 0xd8 && ch <= 0xf6) ||
1503  (ch >= 0xf8 && ch <= 0x2ff) ||
1504  (ch >= 0x370 && ch <= 0x37d) ||
1505  (ch >= 0x37f && ch <= 0x1fff) ||
1506  (ch >= 0x200c && ch <= 0x200d) ||
1507  (ch >= 0x2070 && ch <= 0x218f) ||
1508  (ch >= 0x2c00 && ch <= 0x2fef) ||
1509  (ch >= 0x3001 && ch <= 0xd7ff) ||
1510  (ch >= 0xd800 && ch <= 0xdbff) || /* high surrogate */
1511  (ch >= 0xdc00 && ch <= 0xdfff) || /* low surrogate */
1512  (ch >= 0xf900 && ch <= 0xfdcf) ||
1513  (ch >= 0xfdf0 && ch <= 0xfffd);
1514 }
1515 
1516 /* [4 NS] NCName ::= Name - (Char* ':' Char*) */
1517 static inline BOOL is_ncnamechar(WCHAR ch)
1518 {
1519  return (ch >= 'A' && ch <= 'Z') ||
1520  (ch == '_') || (ch >= 'a' && ch <= 'z') ||
1521  (ch == '-') || (ch == '.') ||
1522  (ch >= '0' && ch <= '9') ||
1523  (ch == 0xb7) ||
1524  (ch >= 0xc0 && ch <= 0xd6) ||
1525  (ch >= 0xd8 && ch <= 0xf6) ||
1526  (ch >= 0xf8 && ch <= 0x2ff) ||
1527  (ch >= 0x300 && ch <= 0x36f) ||
1528  (ch >= 0x370 && ch <= 0x37d) ||
1529  (ch >= 0x37f && ch <= 0x1fff) ||
1530  (ch >= 0x200c && ch <= 0x200d) ||
1531  (ch >= 0x203f && ch <= 0x2040) ||
1532  (ch >= 0x2070 && ch <= 0x218f) ||
1533  (ch >= 0x2c00 && ch <= 0x2fef) ||
1534  (ch >= 0x3001 && ch <= 0xd7ff) ||
1535  (ch >= 0xd800 && ch <= 0xdbff) || /* high surrogate */
1536  (ch >= 0xdc00 && ch <= 0xdfff) || /* low surrogate */
1537  (ch >= 0xf900 && ch <= 0xfdcf) ||
1538  (ch >= 0xfdf0 && ch <= 0xfffd);
1539 }
1540 
1541 static inline BOOL is_namechar(WCHAR ch)
1542 {
1543  return (ch == ':') || is_ncnamechar(ch);
1544 }
1545 
1547 {
1548  /* When we're on attribute always return attribute type, container node type is kept.
1549  Note that container is not necessarily an element, and attribute doesn't mean it's
1550  an attribute in XML spec terms. */
1551  return reader->attr ? XmlNodeType_Attribute : reader->nodetype;
1552 }
1553 
1554 /* [4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] |
1555  [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] |
1556  [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
1557  [4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
1558  [5] Name ::= NameStartChar (NameChar)* */
1560 {
1561  WCHAR *ptr;
1562  UINT start;
1563 
1564  if (reader->resume[XmlReadResume_Name])
1565  {
1566  start = reader->resume[XmlReadResume_Name];
1567  ptr = reader_get_ptr(reader);
1568  }
1569  else
1570  {
1571  ptr = reader_get_ptr(reader);
1572  start = reader_get_cur(reader);
1573  if (!is_namestartchar(*ptr)) return WC_E_NAMECHARACTER;
1574  }
1575 
1576  while (is_namechar(*ptr))
1577  {
1578  reader_skipn(reader, 1);
1579  ptr = reader_get_ptr(reader);
1580  }
1581 
1582  if (is_reader_pending(reader))
1583  {
1584  reader->resume[XmlReadResume_Name] = start;
1585  return E_PENDING;
1586  }
1587  else
1588  reader->resume[XmlReadResume_Name] = 0;
1589 
1590  reader_init_strvalue(start, reader_get_cur(reader)-start, name);
1591  TRACE("name %s:%d\n", debug_strval(reader, name), name->len);
1592 
1593  return S_OK;
1594 }
1595 
1596 /* [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) */
1598 {
1599  static const WCHAR xmlW[] = {'x','m','l'};
1600  static const strval xmlval = { (WCHAR*)xmlW, 3 };
1601  strval name;
1602  WCHAR *ptr;
1603  HRESULT hr;
1604  UINT i;
1605 
1606  hr = reader_parse_name(reader, &name);
1607  if (FAILED(hr)) return is_reader_pending(reader) ? E_PENDING : WC_E_PI;
1608 
1609  /* now that we got name check for illegal content */
1610  if (strval_eq(reader, &name, &xmlval))
1611  return WC_E_LEADINGXML;
1612 
1613  /* PITarget can't be a qualified name */
1614  ptr = reader_get_strptr(reader, &name);
1615  for (i = 0; i < name.len; i++)
1616  if (ptr[i] == ':')
1617  return i ? NC_E_NAMECOLON : WC_E_PI;
1618 
1619  TRACE("pitarget %s:%d\n", debug_strval(reader, &name), name.len);
1620  *target = name;
1621  return S_OK;
1622 }
1623 
1624 /* [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>' */
1626 {
1627  strval target;
1628  WCHAR *ptr;
1629  UINT start;
1630  HRESULT hr;
1631 
1632  switch (reader->resumestate)
1633  {
1635  /* skip '<?' */
1636  reader_skipn(reader, 2);
1637  reader_shrink(reader);
1640  hr = reader_parse_pitarget(reader, &target);
1641  if (FAILED(hr)) return hr;
1642  reader_set_strvalue(reader, StringValue_LocalName, &target);
1644  reader_set_strvalue(reader, StringValue_Value, &strval_empty);
1646  reader->resume[XmlReadResume_Body] = reader_get_cur(reader);
1647  default:
1648  ;
1649  }
1650 
1651  start = reader->resume[XmlReadResume_Body];
1652  ptr = reader_get_ptr(reader);
1653  while (*ptr)
1654  {
1655  if (ptr[0] == '?')
1656  {
1657  if (ptr[1] == '>')
1658  {
1659  UINT cur = reader_get_cur(reader);
1660  strval value;
1661 
1662  /* strip all leading whitespace chars */
1663  while (start < cur)
1664  {
1665  ptr = reader_get_ptr2(reader, start);
1666  if (!is_wchar_space(*ptr)) break;
1667  start++;
1668  }
1669 
1670  reader_init_strvalue(start, cur-start, &value);
1671 
1672  /* skip '?>' */
1673  reader_skipn(reader, 2);
1674  TRACE("%s\n", debug_strval(reader, &value));
1677  reader->resume[XmlReadResume_Body] = 0;
1678  reader_set_strvalue(reader, StringValue_Value, &value);
1679  return S_OK;
1680  }
1681  }
1682 
1683  reader_skipn(reader, 1);
1684  ptr = reader_get_ptr(reader);
1685  }
1686 
1687  return S_OK;
1688 }
1689 
1690 /* This one is used to parse significant whitespace nodes, like in Misc production */
1692 {
1693  switch (reader->resumestate)
1694  {
1696  reader_shrink(reader);
1698  reader->resume[XmlReadResume_Body] = reader_get_cur(reader);
1699  reader->nodetype = XmlNodeType_Whitespace;
1700  reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
1701  reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty);
1702  reader_set_strvalue(reader, StringValue_Value, &strval_empty);
1703  /* fallthrough */
1705  {
1706  strval value;
1707  UINT start;
1708 
1709  reader_skipspaces(reader);
1710  if (is_reader_pending(reader)) return S_OK;
1711 
1712  start = reader->resume[XmlReadResume_Body];
1713  reader_init_strvalue(start, reader_get_cur(reader)-start, &value);
1714  reader_set_strvalue(reader, StringValue_Value, &value);
1715  TRACE("%s\n", debug_strval(reader, &value));
1717  }
1718  default:
1719  ;
1720  }
1721 
1722  return S_OK;
1723 }
1724 
1725 /* [27] Misc ::= Comment | PI | S */
1727 {
1728  HRESULT hr = S_FALSE;
1729 
1730  if (reader->resumestate != XmlReadResumeState_Initial)
1731  {
1732  hr = reader_more(reader);
1733  if (FAILED(hr)) return hr;
1734 
1735  /* finish current node */
1736  switch (reader->resumestate)
1737  {
1740  return reader_parse_pi(reader);
1742  return reader_parse_comment(reader);
1744  return reader_parse_whitespace(reader);
1745  default:
1746  ERR("unknown resume state %d\n", reader->resumestate);
1747  }
1748  }
1749 
1750  while (1)
1751  {
1752  const WCHAR *cur = reader_get_ptr(reader);
1753 
1754  if (is_wchar_space(*cur))
1755  hr = reader_parse_whitespace(reader);
1756  else if (!reader_cmp(reader, commentW))
1757  hr = reader_parse_comment(reader);
1758  else if (!reader_cmp(reader, piW))
1759  hr = reader_parse_pi(reader);
1760  else
1761  break;
1762 
1763  if (hr != S_FALSE) return hr;
1764  }
1765 
1766  return hr;
1767 }
1768 
1769 /* [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") */
1771 {
1772  WCHAR *cur = reader_get_ptr(reader), quote;
1773  UINT start;
1774 
1775  if (*cur != '"' && *cur != '\'') return WC_E_QUOTE;
1776 
1777  quote = *cur;
1778  reader_skipn(reader, 1);
1779 
1780  cur = reader_get_ptr(reader);
1781  start = reader_get_cur(reader);
1782  while (is_char(*cur) && *cur != quote)
1783  {
1784  reader_skipn(reader, 1);
1785  cur = reader_get_ptr(reader);
1786  }
1787  reader_init_strvalue(start, reader_get_cur(reader)-start, literal);
1788  if (*cur == quote) reader_skipn(reader, 1);
1789 
1790  TRACE("%s\n", debug_strval(reader, literal));
1791  return S_OK;
1792 }
1793 
1794 /* [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
1795  [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] */
1797 {
1798  WCHAR *cur = reader_get_ptr(reader), quote;
1799  UINT start;
1800 
1801  if (*cur != '"' && *cur != '\'') return WC_E_QUOTE;
1802 
1803  quote = *cur;
1804  reader_skipn(reader, 1);
1805 
1806  start = reader_get_cur(reader);
1807  cur = reader_get_ptr(reader);
1808  while (is_pubchar(*cur) && *cur != quote)
1809  {
1810  reader_skipn(reader, 1);
1811  cur = reader_get_ptr(reader);
1812  }
1813  reader_init_strvalue(start, reader_get_cur(reader)-start, literal);
1814  if (*cur == quote) reader_skipn(reader, 1);
1815 
1816  TRACE("%s\n", debug_strval(reader, literal));
1817  return S_OK;
1818 }
1819 
1820 /* [75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral */
1822 {
1823  static WCHAR systemW[] = {'S','Y','S','T','E','M',0};
1824  static WCHAR publicW[] = {'P','U','B','L','I','C',0};
1825  struct reader_position position = reader->position;
1826  strval name, sys;
1827  HRESULT hr;
1828  int cnt;
1829 
1830  if (!reader_cmp(reader, publicW)) {
1831  strval pub;
1832 
1833  /* public id */
1834  reader_skipn(reader, 6);
1835  cnt = reader_skipspaces(reader);
1836  if (!cnt) return WC_E_WHITESPACE;
1837 
1838  hr = reader_parse_pub_literal(reader, &pub);
1839  if (FAILED(hr)) return hr;
1840 
1841  reader_init_cstrvalue(publicW, strlenW(publicW), &name);
1842  hr = reader_add_attr(reader, NULL, &name, NULL, &pub, &position, 0);
1843  if (FAILED(hr)) return hr;
1844 
1845  cnt = reader_skipspaces(reader);
1846  if (!cnt) return S_OK;
1847 
1848  /* optional system id */
1849  hr = reader_parse_sys_literal(reader, &sys);
1850  if (FAILED(hr)) return S_OK;
1851 
1852  reader_init_cstrvalue(systemW, strlenW(systemW), &name);
1853  hr = reader_add_attr(reader, NULL, &name, NULL, &sys, &position, 0);
1854  if (FAILED(hr)) return hr;
1855 
1856  return S_OK;
1857  } else if (!reader_cmp(reader, systemW)) {
1858  /* system id */
1859  reader_skipn(reader, 6);
1860  cnt = reader_skipspaces(reader);
1861  if (!cnt) return WC_E_WHITESPACE;
1862 
1863  hr = reader_parse_sys_literal(reader, &sys);
1864  if (FAILED(hr)) return hr;
1865 
1866  reader_init_cstrvalue(systemW, strlenW(systemW), &name);
1867  return reader_add_attr(reader, NULL, &name, NULL, &sys, &position, 0);
1868  }
1869 
1870  return S_FALSE;
1871 }
1872 
1873 /* [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>' */
1875 {
1876  static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',0};
1877  strval name;
1878  WCHAR *cur;
1879  HRESULT hr;
1880 
1881  /* check if we have "<!DOCTYPE" */
1882  if (reader_cmp(reader, doctypeW)) return S_FALSE;
1883  reader_shrink(reader);
1884 
1885  /* DTD processing is not allowed by default */
1886  if (reader->dtdmode == DtdProcessing_Prohibit) return WC_E_DTDPROHIBITED;
1887 
1888  reader_skipn(reader, 9);
1889  if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
1890 
1891  /* name */
1892  hr = reader_parse_name(reader, &name);
1893  if (FAILED(hr)) return WC_E_DECLDOCTYPE;
1894 
1895  reader_skipspaces(reader);
1896 
1897  hr = reader_parse_externalid(reader);
1898  if (FAILED(hr)) return hr;
1899 
1900  reader_skipspaces(reader);
1901 
1902  cur = reader_get_ptr(reader);
1903  if (*cur != '>')
1904  {
1905  FIXME("internal subset parsing not implemented\n");
1906  return E_NOTIMPL;
1907  }
1908 
1909  /* skip '>' */
1910  reader_skipn(reader, 1);
1911 
1915 
1916  return S_OK;
1917 }
1918 
1919 /* [11 NS] LocalPart ::= NCName */
1920 static HRESULT reader_parse_local(xmlreader *reader, strval *local, BOOL check_for_separator)
1921 {
1922  WCHAR *ptr;
1923  UINT start;
1924 
1925  if (reader->resume[XmlReadResume_Local])
1926  {
1927  start = reader->resume[XmlReadResume_Local];
1928  ptr = reader_get_ptr(reader);
1929  }
1930  else
1931  {
1932  ptr = reader_get_ptr(reader);
1933  start = reader_get_cur(reader);
1934  }
1935 
1936  while (is_ncnamechar(*ptr))
1937  {
1938  reader_skipn(reader, 1);
1939  ptr = reader_get_ptr(reader);
1940  }
1941 
1942  if (check_for_separator && *ptr == ':')
1943  return NC_E_QNAMECOLON;
1944 
1945  if (is_reader_pending(reader))
1946  {
1947  reader->resume[XmlReadResume_Local] = start;
1948  return E_PENDING;
1949  }
1950  else
1951  reader->resume[XmlReadResume_Local] = 0;
1952 
1953  reader_init_strvalue(start, reader_get_cur(reader)-start, local);
1954 
1955  return S_OK;
1956 }
1957 
1958 /* [7 NS] QName ::= PrefixedName | UnprefixedName
1959  [8 NS] PrefixedName ::= Prefix ':' LocalPart
1960  [9 NS] UnprefixedName ::= LocalPart
1961  [10 NS] Prefix ::= NCName */
1963 {
1964  WCHAR *ptr;
1965  UINT start;
1966  HRESULT hr;
1967 
1968  if (reader->resume[XmlReadResume_Name])
1969  {
1970  start = reader->resume[XmlReadResume_Name];
1971  ptr = reader_get_ptr(reader);
1972  }
1973  else
1974  {
1975  ptr = reader_get_ptr(reader);
1976  start = reader_get_cur(reader);
1977  reader->resume[XmlReadResume_Name] = start;
1978  if (!is_ncnamechar(*ptr)) return NC_E_QNAMECHARACTER;
1979  }
1980 
1981  if (reader->resume[XmlReadResume_Local])
1982  {
1983  hr = reader_parse_local(reader, local, FALSE);
1984  if (FAILED(hr)) return hr;
1985 
1987  local->start - reader->resume[XmlReadResume_Name] - 1,
1988  prefix);
1989  }
1990  else
1991  {
1992  /* skip prefix part */
1993  while (is_ncnamechar(*ptr))
1994  {
1995  reader_skipn(reader, 1);
1996  ptr = reader_get_ptr(reader);
1997  }
1998 
1999  if (is_reader_pending(reader)) return E_PENDING;
2000 
2001  /* got a qualified name */
2002  if (*ptr == ':')
2003  {
2004  reader_init_strvalue(start, reader_get_cur(reader)-start, prefix);
2005 
2006  /* skip ':' */
2007  reader_skipn(reader, 1);
2008  hr = reader_parse_local(reader, local, TRUE);
2009  if (FAILED(hr)) return hr;
2010  }
2011  else
2012  {
2014  reader_init_strvalue(0, 0, prefix);
2015  }
2016  }
2017 
2018  if (prefix->len)
2019  TRACE("qname %s:%s\n", debug_strval(reader, prefix), debug_strval(reader, local));
2020  else
2021  TRACE("ncname %s\n", debug_strval(reader, local));
2022 
2023  reader_init_strvalue(prefix->len ? prefix->start : local->start,
2024  /* count ':' too */
2025  (prefix->len ? prefix->len + 1 : 0) + local->len,
2026  qname);
2027 
2028  reader->resume[XmlReadResume_Name] = 0;
2029  reader->resume[XmlReadResume_Local] = 0;
2030 
2031  return S_OK;
2032 }
2033 
2034 static WCHAR get_predefined_entity(const xmlreader *reader, const strval *name)
2035 {
2036  static const WCHAR entltW[] = {'l','t'};
2037  static const WCHAR entgtW[] = {'g','t'};
2038  static const WCHAR entampW[] = {'a','m','p'};
2039  static const WCHAR entaposW[] = {'a','p','o','s'};
2040  static const WCHAR entquotW[] = {'q','u','o','t'};
2041  static const strval lt = { (WCHAR*)entltW, 2 };
2042  static const strval gt = { (WCHAR*)entgtW, 2 };
2043  static const strval amp = { (WCHAR*)entampW, 3 };
2044  static const strval apos = { (WCHAR*)entaposW, 4 };
2045  static const strval quot = { (WCHAR*)entquotW, 4 };
2046  WCHAR *str = reader_get_strptr(reader, name);
2047 
2048  switch (*str)
2049  {
2050  case 'l':
2051  if (strval_eq(reader, name, &lt)) return '<';
2052  break;
2053  case 'g':
2054  if (strval_eq(reader, name, &gt)) return '>';
2055  break;
2056  case 'a':
2057  if (strval_eq(reader, name, &amp))
2058  return '&';
2059  else if (strval_eq(reader, name, &apos))
2060  return '\'';
2061  break;
2062  case 'q':
2063  if (strval_eq(reader, name, &quot)) return '\"';
2064  break;
2065  default:
2066  ;
2067  }
2068 
2069  return 0;
2070 }
2071 
2072 /* [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
2073  [67] Reference ::= EntityRef | CharRef
2074  [68] EntityRef ::= '&' Name ';' */
2076 {
2077  encoded_buffer *buffer = &reader->input->buffer->utf16;
2078  WCHAR *start = reader_get_ptr(reader), *ptr;
2079  UINT cur = reader_get_cur(reader);
2080  WCHAR ch = 0;
2081  int len;
2082 
2083  /* skip '&' */
2084  reader_skipn(reader, 1);
2085  ptr = reader_get_ptr(reader);
2086 
2087  if (*ptr == '#')
2088  {
2089  reader_skipn(reader, 1);
2090  ptr = reader_get_ptr(reader);
2091 
2092  /* hex char or decimal */
2093  if (*ptr == 'x')
2094  {
2095  reader_skipn(reader, 1);
2096  ptr = reader_get_ptr(reader);
2097 
2098  while (*ptr != ';')
2099  {
2100  if ((*ptr >= '0' && *ptr <= '9'))
2101  ch = ch*16 + *ptr - '0';
2102  else if ((*ptr >= 'a' && *ptr <= 'f'))
2103  ch = ch*16 + *ptr - 'a' + 10;
2104  else if ((*ptr >= 'A' && *ptr <= 'F'))
2105  ch = ch*16 + *ptr - 'A' + 10;
2106  else
2107  return ch ? WC_E_SEMICOLON : WC_E_HEXDIGIT;
2108  reader_skipn(reader, 1);
2109  ptr = reader_get_ptr(reader);
2110  }
2111  }
2112  else
2113  {
2114  while (*ptr != ';')
2115  {
2116  if ((*ptr >= '0' && *ptr <= '9'))
2117  {
2118  ch = ch*10 + *ptr - '0';
2119  reader_skipn(reader, 1);
2120  ptr = reader_get_ptr(reader);
2121  }
2122  else
2123  return ch ? WC_E_SEMICOLON : WC_E_DIGIT;
2124  }
2125  }
2126 
2127  if (!is_char(ch)) return WC_E_XMLCHARACTER;
2128 
2129  /* normalize */
2130  if (is_wchar_space(ch)) ch = ' ';
2131 
2132  ptr = reader_get_ptr(reader);
2133  start = reader_get_ptr2(reader, cur);
2134  len = buffer->written - ((char *)ptr - buffer->data);
2135  memmove(start + 1, ptr + 1, len);
2136 
2137  buffer->written -= (reader_get_cur(reader) - cur) * sizeof(WCHAR);
2138  buffer->cur = cur + 1;
2139 
2140  *start = ch;
2141  }
2142  else
2143  {
2144  strval name;
2145  HRESULT hr;
2146 
2147  hr = reader_parse_name(reader, &name);
2148  if (FAILED(hr)) return hr;
2149 
2150  ptr = reader_get_ptr(reader);
2151  if (*ptr != ';') return WC_E_SEMICOLON;
2152 
2153  /* predefined entities resolve to a single character */
2154  ch = get_predefined_entity(reader, &name);
2155  if (ch)
2156  {
2157  len = buffer->written - ((char*)ptr - buffer->data) - sizeof(WCHAR);
2158  memmove(start+1, ptr+1, len);
2159  buffer->cur = cur + 1;
2160  buffer->written -= (ptr - start) * sizeof(WCHAR);
2161 
2162  *start = ch;
2163  }
2164  else
2165  {
2166  FIXME("undeclared entity %s\n", debug_strval(reader, &name));
2167  return WC_E_UNDECLAREDENTITY;
2168  }
2169 
2170  }
2171 
2172  return S_OK;
2173 }
2174 
2175 /* [10 NS] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" */
2177 {
2178  WCHAR *ptr, quote;
2179  UINT start;
2180 
2181  ptr = reader_get_ptr(reader);
2182 
2183  /* skip opening quote */
2184  quote = *ptr;
2185  if (quote != '\"' && quote != '\'') return WC_E_QUOTE;
2186  reader_skipn(reader, 1);
2187 
2188  ptr = reader_get_ptr(reader);
2189  start = reader_get_cur(reader);
2190  while (*ptr)
2191  {
2192  if (*ptr == '<') return WC_E_LESSTHAN;
2193 
2194  if (*ptr == quote)
2195  {
2196  reader_init_strvalue(start, reader_get_cur(reader)-start, value);
2197  /* skip closing quote */
2198  reader_skipn(reader, 1);
2199  return S_OK;
2200  }
2201 
2202  if (*ptr == '&')
2203  {
2204  HRESULT hr = reader_parse_reference(reader);
2205  if (FAILED(hr)) return hr;
2206  }
2207  else
2208  {
2209  /* replace all whitespace chars with ' ' */
2210  if (is_wchar_space(*ptr)) *ptr = ' ';
2211  reader_skipn(reader, 1);
2212  }
2213  ptr = reader_get_ptr(reader);
2214  }
2215 
2216  return WC_E_QUOTE;
2217 }
2218 
2219 /* [1 NS] NSAttName ::= PrefixedAttName | DefaultAttName
2220  [2 NS] PrefixedAttName ::= 'xmlns:' NCName
2221  [3 NS] DefaultAttName ::= 'xmlns'
2222  [15 NS] Attribute ::= NSAttName Eq AttValue | QName Eq AttValue */
2224 {
2225  struct reader_position position = reader->position;
2226  strval prefix, local, qname, value;
2227  enum attribute_flags flags = 0;
2228  HRESULT hr;
2229 
2230  hr = reader_parse_qname(reader, &prefix, &local, &qname);
2231  if (FAILED(hr)) return hr;
2232 
2233  if (strval_eq(reader, &prefix, &strval_xmlns))
2234  flags |= ATTRIBUTE_NS_DEFINITION;
2235 
2236  if (strval_eq(reader, &qname, &strval_xmlns))
2238 
2239  hr = reader_parse_eq(reader);
2240  if (FAILED(hr)) return hr;
2241 
2242  hr = reader_parse_attvalue(reader, &value);
2243  if (FAILED(hr)) return hr;
2244 
2246  reader_push_ns(reader, &local, &value, !!(flags & ATTRIBUTE_DEFAULT_NS_DEFINITION));
2247 
2248  TRACE("%s=%s\n", debug_strval(reader, &local), debug_strval(reader, &value));
2249  return reader_add_attr(reader, &prefix, &local, &qname, &value, &position, flags);
2250 }
2251 
2252 /* [12 NS] STag ::= '<' QName (S Attribute)* S? '>'
2253  [14 NS] EmptyElemTag ::= '<' QName (S Attribute)* S? '/>' */
2255 {
2256  struct reader_position position = reader->position;
2257  HRESULT hr;
2258 
2259  hr = reader_parse_qname(reader, prefix, local, qname);
2260  if (FAILED(hr)) return hr;
2261 
2262  for (;;)
2263  {
2264  static const WCHAR endW[] = {'/','>',0};
2265 
2266  reader_skipspaces(reader);
2267 
2268  /* empty element */
2269  if ((reader->is_empty_element = !reader_cmp(reader, endW)))
2270  {
2271  struct element *element = &reader->empty_element;
2272 
2273  /* skip '/>' */
2274  reader_skipn(reader, 2);
2275 
2276  reader_free_strvalued(reader, &element->qname);
2277  reader_free_strvalued(reader, &element->localname);
2278 
2279  element->prefix = *prefix;
2280  reader_strvaldup(reader, qname, &element->qname);
2281  reader_strvaldup(reader, local, &element->localname);
2282  element->position = position;
2283  reader_mark_ns_nodes(reader, element);
2284  return S_OK;
2285  }
2286 
2287  /* got a start tag */
2288  if (!reader_cmp(reader, gtW))
2289  {
2290  /* skip '>' */
2291  reader_skipn(reader, 1);
2292  return reader_push_element(reader, prefix, local, qname, &position);
2293  }
2294 
2295  hr = reader_parse_attribute(reader);
2296  if (FAILED(hr)) return hr;
2297  }
2298 
2299  return S_OK;
2300 }
2301 
2302 /* [39] element ::= EmptyElemTag | STag content ETag */
2304 {
2305  HRESULT hr;
2306 
2307  switch (reader->resumestate)
2308  {
2310  /* check if we are really on element */
2311  if (reader_cmp(reader, ltW)) return S_FALSE;
2312 
2313  /* skip '<' */
2314  reader_skipn(reader, 1);
2315 
2316  reader_shrink(reader);
2319  {
2321 
2322  /* this handles empty elements too */
2323  hr = reader_parse_stag(reader, &prefix, &local, &qname);
2324  if (FAILED(hr)) return hr;
2325 
2326  /* FIXME: need to check for defined namespace to reject invalid prefix */
2327 
2328  /* if we got empty element and stack is empty go straight to Misc */
2329  if (reader->is_empty_element && list_empty(&reader->elements))
2330  reader->instate = XmlReadInState_MiscEnd;
2331  else
2332  reader->instate = XmlReadInState_Content;
2333 
2334  reader->nodetype = XmlNodeType_Element;
2336  reader_set_strvalue(reader, StringValue_Prefix, &prefix);
2338  reader_set_strvalue(reader, StringValue_Value, &strval_empty);
2339  break;
2340  }
2341  default:
2342  hr = E_FAIL;
2343  }
2344 
2345  return hr;
2346 }
2347 
2348 /* [13 NS] ETag ::= '</' QName S? '>' */
2350 {
2351  struct reader_position position;
2352  strval prefix, local, qname;
2353  struct element *element;
2354  HRESULT hr;
2355 
2356  /* skip '</' */
2357  reader_skipn(reader, 2);
2358 
2359  position = reader->position;
2360  hr = reader_parse_qname(reader, &prefix, &local, &qname);
2361  if (FAILED(hr)) return hr;
2362 
2363  reader_skipspaces(reader);
2364 
2365  if (reader_cmp(reader, gtW)) return WC_E_GREATERTHAN;
2366 
2367  /* skip '>' */
2368  reader_skipn(reader, 1);
2369 
2370  /* Element stack should never be empty at this point, cause we shouldn't get to
2371  content parsing if it's empty. */
2372  element = LIST_ENTRY(list_head(&reader->elements), struct element, entry);
2373  if (!strval_eq(reader, &element->qname, &qname)) return WC_E_ELEMENTMATCH;
2374 
2375  /* update position stored for start tag, we won't be using it */
2376  element->position = position;
2377 
2378  reader->nodetype = XmlNodeType_EndElement;
2379  reader->is_empty_element = FALSE;
2380  reader_set_strvalue(reader, StringValue_Prefix, &prefix);
2381 
2382  return S_OK;
2383 }
2384 
2385 /* [18] CDSect ::= CDStart CData CDEnd
2386  [19] CDStart ::= '<![CDATA['
2387  [20] CData ::= (Char* - (Char* ']]>' Char*))
2388  [21] CDEnd ::= ']]>' */
2390 {
2391  WCHAR *ptr;
2392  UINT start;
2393 
2394  if (reader->resumestate == XmlReadResumeState_CDATA)
2395  {
2396  start = reader->resume[XmlReadResume_Body];
2397  ptr = reader_get_ptr(reader);
2398  }
2399  else
2400  {
2401  /* skip markup '<![CDATA[' */
2402  reader_skipn(reader, 9);
2403  reader_shrink(reader);
2404  ptr = reader_get_ptr(reader);
2405  start = reader_get_cur(reader);
2406  reader->nodetype = XmlNodeType_CDATA;
2407  reader->resume[XmlReadResume_Body] = start;
2410  }
2411 
2412  while (*ptr)
2413  {
2414  if (*ptr == ']' && *(ptr+1) == ']' && *(ptr+2) == '>')
2415  {
2416  strval value;
2417 
2418  reader_init_strvalue(start, reader_get_cur(reader)-start, &value);
2419 
2420  /* skip ']]>' */
2421  reader_skipn(reader, 3);
2422  TRACE("%s\n", debug_strval(reader, &value));
2423 
2424  reader_set_strvalue(reader, StringValue_Value, &value);
2425  reader->resume[XmlReadResume_Body] = 0;
2427  return S_OK;
2428  }
2429  else
2430  {
2431  reader_skipn(reader, 1);
2432  ptr++;
2433  }
2434  }
2435 
2436  return S_OK;
2437 }
2438 
2439 /* [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) */
2441 {
2442  struct reader_position position;
2443  WCHAR *ptr;
2444  UINT start;
2445 
2447  {
2448  start = reader->resume[XmlReadResume_Body];
2449  ptr = reader_get_ptr(reader);
2450  }
2451  else
2452  {
2453  reader_shrink(reader);
2454  ptr = reader_get_ptr(reader);
2455  start = reader_get_cur(reader);
2456  /* There's no text */
2457  if (!*ptr || *ptr == '<') return S_OK;
2459  reader->resume[XmlReadResume_Body] = start;
2462  }
2463 
2464  position = reader->position;
2465  while (*ptr)
2466  {
2467  static const WCHAR ampW[] = {'&',0};
2468 
2469  /* CDATA closing sequence ']]>' is not allowed */
2470  if (ptr[0] == ']' && ptr[1] == ']' && ptr[2] == '>')
2471  return WC_E_CDSECTEND;
2472 
2473  /* Found next markup part */
2474  if (ptr[0] == '<')
2475  {
2476  strval value;
2477 
2478  reader->empty_element.position = position;
2479  reader_init_strvalue(start, reader_get_cur(reader)-start, &value);
2480  reader_set_strvalue(reader, StringValue_Value, &value);
2481  reader->resume[XmlReadResume_Body] = 0;
2483  return S_OK;
2484  }
2485 
2486  /* this covers a case when text has leading whitespace chars */
2487  if (!is_wchar_space(*ptr)) reader->nodetype = XmlNodeType_Text;
2488 
2489  if (!reader_cmp(reader, ampW))
2490  reader_parse_reference(reader);
2491  else
2492  reader_skipn(reader, 1);
2493 
2494  ptr = reader_get_ptr(reader);
2495  }
2496 
2497  return S_OK;
2498 }
2499 
2500 /* [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* */
2502 {
2503  static const WCHAR cdstartW[] = {'<','!','[','C','D','A','T','A','[',0};
2504  static const WCHAR etagW[] = {'<','/',0};
2505 
2506  if (reader->resumestate != XmlReadResumeState_Initial)
2507  {
2508  switch (reader->resumestate)
2509  {
2511  return reader_parse_cdata(reader);
2513  return reader_parse_comment(reader);
2516  return reader_parse_pi(reader);
2518  return reader_parse_chardata(reader);
2519  default:
2520  ERR("unknown resume state %d\n", reader->resumestate);
2521  }
2522  }
2523 
2524  reader_shrink(reader);
2525 
2526  /* handle end tag here, it indicates end of content as well */
2527  if (!reader_cmp(reader, etagW))
2528  return reader_parse_endtag(reader);
2529 
2530  if (!reader_cmp(reader, commentW))
2531  return reader_parse_comment(reader);
2532 
2533  if (!reader_cmp(reader, piW))
2534  return reader_parse_pi(reader);
2535 
2536  if (!reader_cmp(reader, cdstartW))
2537  return reader_parse_cdata(reader);
2538 
2539  if (!reader_cmp(reader, ltW))
2540  return reader_parse_element(reader);
2541 
2542  /* what's left must be CharData */
2543  return reader_parse_chardata(reader);
2544 }
2545 
2547 {
2548  XmlNodeType nodetype = reader_get_nodetype(reader);
2549  HRESULT hr;
2550 
2551  if (!is_reader_pending(reader))
2552  {
2553  reader->chunk_read_off = 0;
2554  reader_clear_attrs(reader);
2555  }
2556 
2557  /* When moving from EndElement or empty element, pop its own namespace definitions */
2558  switch (nodetype)
2559  {
2560  case XmlNodeType_Attribute:
2561  reader_dec_depth(reader);
2562  /* fallthrough */
2563  case XmlNodeType_Element:
2564  if (reader->is_empty_element)
2565  reader_pop_ns_nodes(reader, &reader->empty_element);
2566  else if (FAILED(hr = reader_inc_depth(reader)))
2567  return hr;
2568  break;
2570  reader_pop_element(reader);
2571  reader_dec_depth(reader);
2572  break;
2573  default:
2574  ;
2575  }
2576 
2577  for (;;)
2578  {
2579  switch (reader->instate)
2580  {
2581  /* if it's a first call for a new input we need to detect stream encoding */
2583  {
2584  xml_encoding enc;
2585 
2586  hr = readerinput_growraw(reader->input);
2587  if (FAILED(hr)) return hr;
2588 
2589  reader->position.line_number = 1;
2590  reader->position.line_position = 1;
2591 
2592  /* try to detect encoding by BOM or data and set input code page */
2593  hr = readerinput_detectencoding(reader->input, &enc);
2594  TRACE("detected encoding %s, 0x%08x\n", enc == XmlEncoding_Unknown ? "(unknown)" :
2595  debugstr_w(xml_encoding_map[enc].name), hr);
2596  if (FAILED(hr)) return hr;
2597 
2598  /* always switch first time cause we have to put something in */
2599  readerinput_switchencoding(reader->input, enc);
2600 
2601  /* parse xml declaration */
2602  hr = reader_parse_xmldecl(reader);
2603  if (FAILED(hr)) return hr;
2604 
2605  readerinput_shrinkraw(reader->input, -1);
2606  reader->instate = XmlReadInState_Misc_DTD;
2607  if (hr == S_OK) return hr;
2608  }
2609  break;
2611  hr = reader_parse_misc(reader);
2612  if (FAILED(hr)) return hr;
2613 
2614  if (hr == S_FALSE)
2615  reader->instate = XmlReadInState_DTD;
2616  else
2617  return hr;
2618  break;
2619  case XmlReadInState_DTD:
2620  hr = reader_parse_dtd(reader);
2621  if (FAILED(hr)) return hr;
2622 
2623  if (hr == S_OK)
2624  {
2625  reader->instate = XmlReadInState_DTD_Misc;
2626  return hr;
2627  }
2628  else
2629  reader->instate = XmlReadInState_Element;
2630  break;
2632  hr = reader_parse_misc(reader);
2633  if (FAILED(hr)) return hr;
2634 
2635  if (hr == S_FALSE)
2636  reader->instate = XmlReadInState_Element;
2637  else
2638  return hr;
2639  break;
2641  return reader_parse_element(reader);
2643  return reader_parse_content(reader);
2645  hr = reader_parse_misc(reader);
2646  if (hr != S_FALSE) return hr;
2647 
2648  if (*reader_get_ptr(reader))
2649  {
2650  WARN("found garbage in the end of XML\n");
2651  return WC_E_SYNTAX;
2652  }
2653 
2654  reader->instate = XmlReadInState_Eof;
2655  reader->state = XmlReadState_EndOfFile;
2656  reader->nodetype = XmlNodeType_None;
2657  return hr;
2658  case XmlReadInState_Eof:
2659  return S_FALSE;
2660  default:
2661  FIXME("internal state %d not handled\n", reader->instate);
2662  return E_NOTIMPL;
2663  }
2664  }
2665 
2666  return E_NOTIMPL;
2667 }
2668 
2670 {
2671  xmlreader *This = impl_from_IXmlReader(iface);
2672 
2673  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
2674 
2675  if (IsEqualGUID(riid, &IID_IUnknown) ||
2676  IsEqualGUID(riid, &IID_IXmlReader))
2677  {
2678  *ppvObject = iface;
2679  }
2680  else
2681  {
2682  FIXME("interface %s not implemented\n", debugstr_guid(riid));
2683  *ppvObject = NULL;
2684  return E_NOINTERFACE;
2685  }
2686 
2687  IXmlReader_AddRef(iface);
2688 
2689  return S_OK;
2690 }
2691 
2693 {
2694  xmlreader *This = impl_from_IXmlReader(iface);
2695  ULONG ref = InterlockedIncrement(&This->ref);
2696  TRACE("(%p)->(%d)\n", This, ref);
2697  return ref;
2698 }
2699 
2700 static void reader_clear_ns(xmlreader *reader)
2701 {
2702  struct ns *ns, *ns2;
2703 
2704  LIST_FOR_EACH_ENTRY_SAFE(ns, ns2, &reader->ns, struct ns, entry) {
2705  list_remove(&ns->entry);
2706  reader_free_strvalued(reader, &ns->prefix);
2707  reader_free_strvalued(reader, &ns->uri);
2708  reader_free(reader, ns);
2709  }
2710 
2711  LIST_FOR_EACH_ENTRY_SAFE(ns, ns2, &reader->nsdef, struct ns, entry) {
2712  list_remove(&ns->entry);
2713  reader_free_strvalued(reader, &ns->uri);
2714  reader_free(reader, ns);
2715  }
2716 }
2717 
2718 static void reader_reset_parser(xmlreader *reader)
2719 {
2720  reader->position.line_number = 0;
2721  reader->position.line_position = 0;
2722 
2723  reader_clear_elements(reader);
2724  reader_clear_attrs(reader);
2725  reader_clear_ns(reader);
2726  reader_free_strvalues(reader);
2727 
2728  reader->depth = 0;
2729  reader->nodetype = XmlNodeType_None;
2731  memset(reader->resume, 0, sizeof(reader->resume));
2732  reader->is_empty_element = FALSE;
2733 }
2734 
2736 {
2737  xmlreader *This = impl_from_IXmlReader(iface);
2738  LONG ref = InterlockedDecrement(&This->ref);
2739 
2740  TRACE("(%p)->(%d)\n", This, ref);
2741 
2742  if (ref == 0)
2743  {
2744  IMalloc *imalloc = This->imalloc;
2745  reader_reset_parser(This);
2746  if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface);
2747  if (This->resolver) IXmlResolver_Release(This->resolver);
2748  if (This->mlang) IUnknown_Release(This->mlang);
2749  reader_free(This, This);
2750  if (imalloc) IMalloc_Release(imalloc);
2751  }
2752 
2753  return ref;
2754 }
2755 
2757 {
2758  xmlreader *This = impl_from_IXmlReader(iface);
2759  IXmlReaderInput *readerinput;
2760  HRESULT hr;
2761 
2762  TRACE("(%p)->(%p)\n", This, input);
2763 
2764  if (This->input)
2765  {
2767  IUnknown_Release(&This->input->IXmlReaderInput_iface);
2768  This->input = NULL;
2769  }
2770 
2771  reader_reset_parser(This);
2772 
2773  /* just reset current input */
2774  if (!input)
2775  {
2776  This->state = XmlReadState_Initial;
2777  return S_OK;
2778  }
2779 
2780  /* now try IXmlReaderInput, ISequentialStream, IStream */
2781  hr = IUnknown_QueryInterface(input, &IID_IXmlReaderInput, (void**)&readerinput);
2782  if (hr == S_OK)
2783  {
2784  if (readerinput->lpVtbl == &xmlreaderinputvtbl)
2785  This->input = impl_from_IXmlReaderInput(readerinput);
2786  else
2787  {
2788  ERR("got external IXmlReaderInput implementation: %p, vtbl=%p\n",
2789  readerinput, readerinput->lpVtbl);
2790  IUnknown_Release(readerinput);
2791  return E_FAIL;
2792 
2793  }
2794  }
2795 
2796  if (hr != S_OK || !readerinput)
2797  {
2798  /* create IXmlReaderInput basing on supplied interface */
2800  This->imalloc, NULL, FALSE, NULL, &readerinput);
2801  if (hr != S_OK) return hr;
2802  This->input = impl_from_IXmlReaderInput(readerinput);
2803  }
2804 
2805  /* set stream for supplied IXmlReaderInput */
2806  hr = readerinput_query_for_stream(This->input);
2807  if (hr == S_OK)
2808  {
2809  This->state = XmlReadState_Initial;
2811  }
2812  return hr;
2813 }
2814 
2816 {
2817  xmlreader *This = impl_from_IXmlReader(iface);
2818 
2819  TRACE("(%p)->(%s %p)\n", This, debugstr_reader_prop(property), value);
2820 
2821  if (!value) return E_INVALIDARG;
2822 
2823  switch (property)
2824  {
2826  *value = (LONG_PTR)This->mlang;
2827  if (This->mlang)
2828  IUnknown_AddRef(This->mlang);
2829  break;
2831  *value = (LONG_PTR)This->resolver;
2832  if (This->resolver)
2833  IXmlResolver_AddRef(This->resolver);
2834  break;
2836  *value = This->dtdmode;
2837  break;
2839  *value = This->state;
2840  break;
2842  *value = This->max_depth;
2843  break;
2844  default:
2845  FIXME("Unimplemented property (%u)\n", property);
2846  return E_NOTIMPL;
2847  }
2848 
2849  return S_OK;
2850 }
2851 
2853 {
2854  xmlreader *This = impl_from_IXmlReader(iface);
2855 
2856  TRACE("(%p)->(%s 0x%lx)\n", This, debugstr_reader_prop(property), value);
2857 
2858  switch (property)
2859  {
2861  if (This->mlang)
2862  IUnknown_Release(This->mlang);
2863  This->mlang = (IUnknown*)value;
2864  if (This->mlang)
2865  IUnknown_AddRef(This->mlang);
2866  if (This->mlang)
2867  FIXME("Ignoring MultiLanguage %p\n", This->mlang);
2868  break;
2870  if (This->resolver)
2871  IXmlResolver_Release(This->resolver);
2872  This->resolver = (IXmlResolver*)value;
2873  if (This->resolver)
2874  IXmlResolver_AddRef(This->resolver);
2875  break;
2878  This->dtdmode = value;
2879  break;
2881  This->max_depth = value;
2882  break;
2883  default:
2884  FIXME("Unimplemented property (%u)\n", property);
2885  return E_NOTIMPL;
2886  }
2887 
2888  return S_OK;
2889 }
2890 
2892 {
2893  xmlreader *This = impl_from_IXmlReader(iface);
2894  XmlNodeType oldtype = This->nodetype;
2895  XmlNodeType type;
2896  HRESULT hr;
2897 
2898  TRACE("(%p)->(%p)\n", This, nodetype);
2899 
2900  if (!nodetype)
2901  nodetype = &type;
2902 
2903  switch (This->state)
2904  {
2905  case XmlReadState_Closed:
2906  hr = S_FALSE;
2907  break;
2908  case XmlReadState_Error:
2909  hr = This->error;
2910  break;
2911  default:
2912  hr = reader_parse_nextnode(This);
2913  if (SUCCEEDED(hr) && oldtype == XmlNodeType_None && This->nodetype != oldtype)
2915 
2916  if (FAILED(hr))
2917  {
2918  This->state = XmlReadState_Error;
2919  This->nodetype = XmlNodeType_None;
2920  This->depth = 0;
2921  This->error = hr;
2922  }
2923  }
2924 
2925  TRACE("node type %s\n", debugstr_nodetype(This->nodetype));
2926  *nodetype = This->nodetype;
2927 
2928  return hr;
2929 }
2930 
2932 {
2933  xmlreader *This = impl_from_IXmlReader(iface);
2934 
2935  TRACE("(%p)->(%p)\n", This, node_type);
2936 
2937  if (!node_type)
2938  return E_INVALIDARG;
2939 
2940  *node_type = reader_get_nodetype(This);
2941  return This->state == XmlReadState_Closed ? S_FALSE : S_OK;
2942 }
2943 
2945 {
2946  reader->attr = attr;
2947  reader->chunk_read_off = 0;
2950  reader_set_strvalue(reader, StringValue_Value, &attr->value);
2951 }
2952 
2954 {
2955  if (!reader->attr_count)
2956  return S_FALSE;
2957 
2958  if (!reader->attr)
2959  reader_inc_depth(reader);
2960 
2962 
2963  return S_OK;
2964 }
2965 
2967 {
2968  xmlreader *This = impl_from_IXmlReader(iface);
2969 
2970  TRACE("(%p)\n", This);
2971 
2972  return reader_move_to_first_attribute(This);
2973 }
2974 
2976 {
2977  xmlreader *This = impl_from_IXmlReader(iface);
2978  const struct list *next;
2979 
2980  TRACE("(%p)\n", This);
2981 
2982  if (!This->attr_count) return S_FALSE;
2983 
2984  if (!This->attr)
2985  return reader_move_to_first_attribute(This);
2986 
2987  next = list_next(&This->attrs, &This->attr->entry);
2988  if (next)
2990 
2991  return next ? S_OK : S_FALSE;
2992 }
2993 
2994 static void reader_get_attribute_ns_uri(xmlreader *reader, struct attribute *attr, const WCHAR **uri, UINT *len)
2995 {
2996  static const WCHAR xmlns_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
2997  '2','0','0','0','/','x','m','l','n','s','/',0};
2998  static const WCHAR xml_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
2999  'X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0};
3000 
3001  /* Check for reserved prefixes first */
3002  if ((strval_eq(reader, &attr->prefix, &strval_empty) && strval_eq(reader, &attr->localname, &strval_xmlns)) ||
3003  strval_eq(reader, &attr->prefix, &strval_xmlns))
3004  {
3005  *uri = xmlns_uriW;
3006  *len = sizeof(xmlns_uriW)/sizeof(xmlns_uriW[0]) - 1;
3007  }
3008  else if (strval_eq(reader, &attr->prefix, &strval_xml))
3009  {
3010  *uri = xml_uriW;
3011  *len = sizeof(xml_uriW)/sizeof(xml_uriW[0]) - 1;
3012  }
3013  else
3014  {
3015  *uri = NULL;
3016  *len = 0;
3017  }
3018 
3019  if (!*uri)
3020  {
3021  struct ns *ns;
3022 
3023  if ((ns = reader_lookup_ns(reader, &attr->prefix)))
3024  {
3025  *uri = ns->uri.str;
3026  *len = ns->uri.len;
3027  }
3028  else
3029  {
3030  *uri = emptyW;
3031  *len = 0;
3032  }
3033  }
3034 }
3035 
3036 static void reader_get_attribute_local_name(xmlreader *reader, struct attribute *attr, const WCHAR **name, UINT *len)
3037 {
3039  {
3040  *name = xmlnsW;
3041  *len = 5;
3042  }
3043  else if (attr->flags & ATTRIBUTE_NS_DEFINITION)
3044  {
3045  const struct ns *ns = reader_lookup_ns(reader, &attr->localname);
3046  *name = ns->prefix.str;
3047  *len = ns->prefix.len;
3048  }
3049  else
3050  {
3051  *name = attr->localname.str;
3052  *len = attr->localname.len;
3053  }
3054 }
3055 
3057  const WCHAR *local_name, const WCHAR *namespace_uri)
3058 {
3059  xmlreader *This = impl_from_IXmlReader(iface);
3060  UINT target_name_len, target_uri_len;
3061  struct attribute *attr;
3062 
3063  TRACE("(%p)->(%s %s)\n", This, debugstr_w(local_name), debugstr_w(namespace_uri));
3064 
3065  if (!local_name)
3066  return E_INVALIDARG;
3067 
3068  if (!This->attr_count)
3069  return S_FALSE;
3070 
3071  if (!namespace_uri)
3072  namespace_uri = emptyW;
3073 
3074  target_name_len = strlenW(local_name);
3075  target_uri_len = strlenW(namespace_uri);
3076 
3077  LIST_FOR_EACH_ENTRY(attr, &This->attrs, struct attribute, entry)
3078  {
3079  UINT name_len, uri_len;
3080  const WCHAR *name, *uri;
3081 
3082  reader_get_attribute_local_name(This, attr, &name, &name_len);
3083  reader_get_attribute_ns_uri(This, attr, &uri, &uri_len);
3084 
3085  if (name_len == target_name_len && uri_len == target_uri_len &&
3086  !strcmpW(name, local_name) && !strcmpW(uri, namespace_uri))
3087  {
3088  reader_set_current_attribute(This, attr);
3089  return S_OK;
3090  }
3091  }
3092 
3093  return S_FALSE;
3094 }
3095 
3097 {
3098  xmlreader *This = impl_from_IXmlReader(iface);
3099 
3100  TRACE("(%p)\n", This);
3101 
3102  if (!This->attr_count) return S_FALSE;
3103 
3104  if (This->attr)
3105  reader_dec_depth(This);
3106 
3107  This->attr = NULL;
3108 
3109  /* FIXME: support other node types with 'attributes' like DTD */
3110  if (This->is_empty_element) {
3113  }
3114  else {
3115  struct element *element = LIST_ENTRY(list_head(&This->elements), struct element, entry);
3116  if (element) {
3117  reader_set_strvalue(This, StringValue_Prefix, &element->prefix);
3119  }
3120  }
3121  This->chunk_read_off = 0;
3122  reader_set_strvalue(This, StringValue_Value, &strval_empty);
3123 
3124  return S_OK;
3125 }
3126 
3128 {
3129  xmlreader *This = impl_from_IXmlReader(iface);
3130  struct attribute *attribute = This->attr;
3131  struct element *element;
3132  UINT length;
3133 
3134  TRACE("(%p)->(%p %p)\n", This, name, len);
3135 
3136  if (!len)
3137  len = &length;
3138 
3139  switch (reader_get_nodetype(This))
3140  {
3141  case XmlNodeType_Text:
3142  case XmlNodeType_CDATA:
3143  case XmlNodeType_Comment:
3145  *name = emptyW;
3146  *len = 0;
3147  break;
3148  case XmlNodeType_Element:
3150  element = reader_get_element(This);
3151  if (element->prefix.len)
3152  {
3153  *name = element->qname.str;
3154  *len = element->qname.len;
3155  }
3156  else
3157  {
3158  *name = element->localname.str;
3159  *len = element->localname.len;
3160  }
3161  break;
3162  case XmlNodeType_Attribute:
3163  if (attribute->flags & ATTRIBUTE_DEFAULT_NS_DEFINITION)
3164  {
3165  *name = xmlnsW;
3166  *len = 5;
3167  } else if (attribute->prefix.len)
3168  {
3169  *name = This->strvalues[StringValue_QualifiedName].str;
3170  *len = This->strvalues[StringValue_QualifiedName].len;
3171  }
3172  else
3173  {
3174  *name = attribute->localname.str;
3175  *len = attribute->localname.len;
3176  }
3177  break;
3178  default:
3179  *name = This->strvalues[StringValue_QualifiedName].str;
3180  *len = This->strvalues[StringValue_QualifiedName].len;
3181  break;
3182  }
3183 
3184  return S_OK;
3185 }
3186 
3187 static struct ns *reader_lookup_nsdef(xmlreader *reader)
3188 {
3189  if (list_empty(&reader->nsdef))
3190  return NULL;
3191 
3192  return LIST_ENTRY(list_head(&reader->nsdef), struct ns, entry);
3193 }
3194 
3196 {
3197  xmlreader *This = impl_from_IXmlReader(iface);
3198  const strval *prefix = &This->strvalues[StringValue_Prefix];
3199  XmlNodeType nodetype;
3200  struct ns *ns;
3201  UINT length;
3202 
3203  TRACE("(%p %p %p)\n", iface, uri, len);
3204 
3205  if (!len)
3206  len = &length;
3207 
3208  switch ((nodetype = reader_get_nodetype(This)))
3209  {
3210  case XmlNodeType_Attribute:
3211  reader_get_attribute_ns_uri(This, This->attr, uri, len);
3212  break;
3213  case XmlNodeType_Element:
3215  {
3216  ns = reader_lookup_ns(This, prefix);
3217 
3218  /* pick top default ns if any */
3219  if (!ns)
3220  ns = reader_lookup_nsdef(This);
3221 
3222  if (ns) {
3223  *uri = ns->uri.str;
3224  *len = ns->uri.len;
3225  }
3226  else {
3227  *uri = emptyW;
3228  *len = 0;
3229  }
3230  }
3231  break;
3232  case XmlNodeType_Text:
3233  case XmlNodeType_CDATA:
3235  case XmlNodeType_Comment:
3238  *uri = emptyW;
3239  *len = 0;
3240  break;
3241  default:
3242  FIXME("Unhandled node type %d\n", nodetype);
3243  *uri = NULL;
3244  *len = 0;
3245  return E_NOTIMPL;
3246  }
3247 
3248  return S_OK;
3249 }
3250 
3252 {
3253  xmlreader *This = impl_from_IXmlReader(iface);
3254  struct element *element;
3255  UINT length;
3256 
3257  TRACE("(%p)->(%p %p)\n", This, name, len);
3258 
3259  if (!len)
3260  len = &length;
3261 
3262  switch (reader_get_nodetype(This))
3263  {
3264  case XmlNodeType_Text:
3265  case XmlNodeType_CDATA:
3266  case XmlNodeType_Comment:
3268  *name = emptyW;
3269  *len = 0;
3270  break;
3271  case XmlNodeType_Element:
3273  element = reader_get_element(This);
3274  *name = element->localname.str;
3275  *len = element->localname.len;
3276  break;
3277  case XmlNodeType_Attribute:
3278  reader_get_attribute_local_name(This, This->attr, name, len);
3279  break;
3280  default:
3281  *name = This->strvalues[StringValue_LocalName].str;
3282  *len = This->strvalues[StringValue_LocalName].len;
3283  break;
3284  }
3285 
3286  return S_OK;
3287 }
3288 
3290 {
3291  xmlreader *This = impl_from_IXmlReader(iface);
3292  XmlNodeType nodetype;
3293  UINT length;
3294 
3295  TRACE("(%p)->(%p %p)\n", This, ret, len);
3296 
3297  if (!len)
3298  len = &length;
3299 
3300  *ret = emptyW;
3301  *len = 0;
3302 
3303  switch ((nodetype = reader_get_nodetype(This)))
3304  {
3305  case XmlNodeType_Element:
3307  case XmlNodeType_Attribute:
3308  {
3309  const strval *prefix = &This->strvalues[StringValue_Prefix];
3310  struct ns *ns;
3311 
3312  if (strval_eq(This, prefix, &strval_xml))
3313  {
3314  *ret = xmlW;
3315  *len = 3;
3316  }
3317  else if (strval_eq(This, prefix, &strval_xmlns))
3318  {
3319  *ret = xmlnsW;
3320  *len = 5;
3321  }
3322  else if ((ns = reader_lookup_ns(This, prefix)))
3323  {
3324  *ret = ns->prefix.str;
3325  *len = ns->prefix.len;
3326  }
3327 
3328  break;
3329  }
3330  default:
3331  ;
3332  }
3333 
3334  return S_OK;
3335 }
3336 
3337 static const strval *reader_get_value(xmlreader *reader, BOOL ensure_allocated)
3338 {
3339  strval *val;
3340 
3341  switch (reader_get_nodetype(reader))
3342  {
3345  case XmlNodeType_None:
3346  return &strval_empty;
3347  case XmlNodeType_Attribute:
3348  /* For namespace definition attributes return values from namespace list */
3350  {
3351  struct ns *ns;
3352 
3353  if (!(ns = reader_lookup_ns(reader, &reader->attr->localname)))
3354  ns = reader_lookup_nsdef(reader);
3355 
3356  return &ns->uri;
3357  }
3358  return &reader->attr->value;
3359  default:
3360  break;
3361  }
3362 
3363  val = &reader->strvalues[StringValue_Value];
3364  if (!val->str && ensure_allocated)
3365  {
3366  WCHAR *ptr = reader_alloc(reader, (val->len+1)*sizeof(WCHAR));
3367  if (!ptr) return NULL;
3368  memcpy(ptr, reader_get_strptr(reader, val), val->len*sizeof(WCHAR));
3369  ptr[val->len] = 0;
3370  val->str = ptr;
3371  }
3372 
3373  return val;
3374 }
3375 
3377 {
3378  xmlreader *reader = impl_from_IXmlReader(iface);
3379  const strval *val = &reader->strvalues[StringValue_Value];
3380  UINT off;
3381 
3382  TRACE("(%p)->(%p %p)\n", reader, value, len);
3383 
3384  *value = NULL;
3385 
3386  if ((reader->nodetype == XmlNodeType_Comment && !val->str && !val->len) || is_reader_pending(reader))
3387  {
3388  XmlNodeType type;
3389  HRESULT hr;
3390 
3391  hr = IXmlReader_Read(iface, &type);
3392  if (FAILED(hr)) return hr;
3393 
3394  /* return if still pending, partially read values are not reported */
3395  if (is_reader_pending(reader)) return E_PENDING;
3396  }
3397 
3398  val = reader_get_value(reader, TRUE);
3399  if (!val)
3400  return E_OUTOFMEMORY;
3401 
3402  off = abs(reader->chunk_read_off);
3403  assert(off <= val->len);
3404  *value = val->str + off;
3405  if (len) *len = val->len - off;
3406  reader->chunk_read_off = -off;
3407  return S_OK;
3408 }
3409 
3411 {
3412  xmlreader *reader = impl_from_IXmlReader(iface);
3413  const strval *val;
3414  UINT len = 0;
3415 
3416  TRACE("(%p)->(%p %u %p)\n", reader, buffer, chunk_size, read);
3417 
3418  val = reader_get_value(reader, FALSE);
3419 
3420  /* If value is already read by GetValue, chunk_read_off is negative and chunked reads are not possible. */
3421  if (reader->chunk_read_off >= 0)
3422  {
3423  assert(reader->chunk_read_off <= val->len);
3424  len = min(val->len - reader->chunk_read_off, chunk_size);
3425  }
3426  if (read) *read = len;
3427 
3428  if (len)
3429  {
3430  memcpy(buffer, reader_get_strptr(reader, val) + reader->chunk_read_off, len*sizeof(WCHAR));
3431  reader->chunk_read_off += len;
3432  }
3433 
3434  return len || !chunk_size ? S_OK : S_FALSE;
3435 }
3436 
3438  LPCWSTR *baseUri,
3439  UINT *baseUri_length)
3440 {
3441  FIXME("(%p %p %p): stub\n", iface, baseUri, baseUri_length);
3442  return E_NOTIMPL;
3443 }
3444 
3446 {
3447  FIXME("(%p): stub\n", iface);
3448  return FALSE;
3449 }
3450 
3452 {
3453  xmlreader *This = impl_from_IXmlReader(iface);
3454  TRACE("(%p)\n", This);
3455  /* Empty elements are not placed in stack, it's stored as a global reader flag that makes sense
3456  when current node is start tag of an element */
3457  return (reader_get_nodetype(This) == XmlNodeType_Element) ? This->is_empty_element : FALSE;
3458 }
3459 
3461 {
3462  xmlreader *This = impl_from_IXmlReader(iface);
3463  const struct element *element;
3464 
3465  TRACE("(%p %p)\n", This, line_number);
3466 
3467  if (!line_number)
3468  return E_INVALIDARG;
3469 
3470  switch (reader_get_nodetype(This))
3471  {
3472  case XmlNodeType_Element:
3474  element = reader_get_element(This);
3475  *line_number = element->position.line_number;
3476  break;
3477  case XmlNodeType_Attribute:
3478  *line_number = This->attr->position.line_number;
3479  break;
3482  *line_number = This->empty_element.position.line_number;
3483  break;
3484  default:
3485  *line_number = This->position.line_number;
3486  break;
3487  }
3488 
3489  return This->state == XmlReadState_Closed ? S_FALSE : S_OK;
3490 }
3491 
3493 {
3494  xmlreader *This = impl_from_IXmlReader(iface);
3495  const struct element *element;
3496 
3497  TRACE("(%p %p)\n", This, line_position);
3498 
3499  if (!line_position)
3500  return E_INVALIDARG;
3501 
3502  switch (reader_get_nodetype(This))
3503  {
3504  case XmlNodeType_Element:
3506  element = reader_get_element(This);
3507  *line_position = element->position.line_position;
3508  break;
3509  case XmlNodeType_Attribute:
3510  *line_position = This->attr->position.line_position;
3511  break;
3514  *line_position = This->empty_element.position.line_position;
3515  break;
3516  default:
3517  *line_position = This->position.line_position;
3518  break;
3519  }
3520 
3521  return This->state == XmlReadState_Closed ? S_FALSE : S_OK;
3522 }
3523 
3525 {
3526  xmlreader *This = impl_from_IXmlReader(iface);
3527 
3528  TRACE("(%p)->(%p)\n", This, count);
3529 
3530  if (!count) return E_INVALIDARG;
3531 
3532  *count = This->attr_count;
3533  return S_OK;
3534 }
3535 
3537 {
3538  xmlreader *This = impl_from_IXmlReader(iface);
3539  TRACE("(%p)->(%p)\n", This, depth);
3540  *depth = This->depth;
3541  return S_OK;
3542 }
3543 
3545 {
3546  xmlreader *This = impl_from_IXmlReader(iface);
3547  TRACE("(%p)\n", iface);
3548  return This->state == XmlReadState_EndOfFile;
3549 }
3550 
3551 static const struct IXmlReaderVtbl xmlreader_vtbl =
3552 {
3579 };
3580 
3583 {
3585 
3586  TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
3587 
3588  if (IsEqualGUID(riid, &IID_IXmlReaderInput) ||
3589  IsEqualGUID(riid, &IID_IUnknown))
3590  {
3591  *ppvObject = iface;
3592  }
3593  else
3594  {
3595  WARN("interface %s not implemented\n", debugstr_guid(riid));
3596  *ppvObject = NULL;
3597  return E_NOINTERFACE;
3598  }
3599 
3600  IUnknown_AddRef(iface);
3601 
3602  return S_OK;
3603 }
3604 
3606 {
3608  ULONG ref = InterlockedIncrement(&This->ref);
3609  TRACE("(%p)->(%d)\n", This, ref);
3610  return ref;
3611 }
3612 
3614 {
3616  LONG ref = InterlockedDecrement(&This->ref);
3617 
3618  TRACE("(%p)->(%d)\n", This, ref);
3619 
3620  if (ref == 0)
3621  {
3622  IMalloc *imalloc = This->imalloc;
3623  if (This->input) IUnknown_Release(This->input);
3624  if (This->stream) ISequentialStream_Release(This->stream);
3625  if (This->buffer) free_input_buffer(This->buffer);
3626  readerinput_free(This, This->baseuri);
3627  readerinput_free(This, This);
3628  if (imalloc) IMalloc_Release(imalloc);
3629  }
3630 
3631  return ref;
3632 }
3633 
3634 static const struct IUnknownVtbl xmlreaderinputvtbl =
3635 {
3639 };
3640 
3642 {
3643  xmlreader *reader;
3644  HRESULT hr;
3645  int i;
3646 
3647  TRACE("(%s, %p, %p)\n", wine_dbgstr_guid(riid), obj, imalloc);
3648 
3649  if (imalloc)
3650  reader = IMalloc_Alloc(imalloc, sizeof(*reader));
3651  else
3652  reader = heap_alloc(sizeof(*reader));
3653  if (!reader)
3654  return E_OUTOFMEMORY;
3655 
3656  memset(reader, 0, sizeof(*reader));
3657  reader->IXmlReader_iface.lpVtbl = &xmlreader_vtbl;
3658  reader->ref = 1;
3659  reader->state = XmlReadState_Closed;
3660  reader->instate = XmlReadInState_Initial;
3662  reader->dtdmode = DtdProcessing_Prohibit;
3663  reader->imalloc = imalloc;
3664  if (imalloc) IMalloc_AddRef(imalloc);
3665  reader->nodetype = XmlNodeType_None;
3666  list_init(&reader->attrs);
3667  list_init(&reader->nsdef);
3668  list_init(&reader->ns);
3669  list_init(&reader->elements);
3670  reader->max_depth = 256;
3671 
3672  reader->chunk_read_off = 0;
3673  for (i = 0; i < StringValue_Last; i++)
3674  reader->strvalues[i] = strval_empty;
3675 
3676  hr = IXmlReader_QueryInterface(&reader->IXmlReader_iface, riid, obj);
3677  IXmlReader_Release(&reader->IXmlReader_iface);
3678 
3679  TRACE("returning iface %p, hr %#x\n", *obj, hr);
3680 
3681  return hr;
3682 }
3683 
3685  IMalloc *imalloc,
3686  LPCWSTR encoding,
3687  BOOL hint,
3688  LPCWSTR base_uri,
3689  IXmlReaderInput **ppInput)
3690 {
3691  xmlreaderinput *readerinput;
3692  HRESULT hr;
3693 
3694  TRACE("%p %p %s %d %s %p\n", stream, imalloc, wine_dbgstr_w(encoding),
3695  hint, wine_dbgstr_w(base_uri), ppInput);
3696 
3697  if (!stream || !ppInput) return E_INVALIDARG;
3698 
3699  if (imalloc)
3700  readerinput = IMalloc_Alloc(imalloc, sizeof(*readerinput));
3701  else
3702  readerinput = heap_alloc(sizeof(*readerinput));
3703  if(!readerinput) return E_OUTOFMEMORY;
3704 
3705  readerinput->IXmlReaderInput_iface.lpVtbl = &xmlreaderinputvtbl;
3706  readerinput->ref = 1;
3707  readerinput->imalloc = imalloc;
3708  readerinput->stream = NULL;
3709  if (imalloc) IMalloc_AddRef(imalloc);
3710  readerinput->encoding = parse_encoding_name(encoding, -1);
3711  readerinput->hint = hint;
3712  readerinput->baseuri = readerinput_strdupW(readerinput, base_uri);
3713  readerinput->pending = 0;
3714 
3715  hr = alloc_input_buffer(readerinput);
3716  if (hr != S_OK)
3717  {
3718  readerinput_free(readerinput, readerinput->baseuri);
3719  readerinput_free(readerinput, readerinput);
3720  if (imalloc) IMalloc_Release(imalloc);
3721  return hr;
3722  }
3723  IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&readerinput->input);
3724 
3725  *ppInput = &readerinput->IXmlReaderInput_iface;
3726 
3727  TRACE("returning iface %p\n", *ppInput);
3728 
3729  return S_OK;
3730 }
char * data
Definition: mxwriter.c:102
static void reader_free_element(xmlreader *reader, struct element *element)
Definition: reader.c:568
WCHAR * str
Definition: reader.c:209
static HRESULT reader_more(xmlreader *reader)
Definition: reader.c:1061
static const struct IXmlReaderVtbl xmlreader_vtbl
Definition: reader.c:3551
static const WCHAR utf16W[]
Definition: reader.c:78
static HRESULT reader_parse_dtd(xmlreader *reader)
Definition: reader.c:1874
int chunk_read_off
Definition: reader.c:282
XmlReadState
Definition: xmllite.idl:97
static const strval strval_empty
Definition: reader.c:217
#define abs(i)
Definition: fconv.c:206
static WCHAR xmlW[]
Definition: reader.c:215
static BOOL WINAPI xmlreader_IsDefault(IXmlReader *iface)
Definition: reader.c:3445
static void fixup_buffer_cr(encoded_buffer *buffer, int off)
Definition: reader.c:978
const WCHAR * name
Definition: reader.c:142
xml_encoding encoding
Definition: reader.c:186
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define max(a, b)
Definition: svc.c:63
Definition: get.c:139
struct reader_position position
Definition: reader.c:275
#define REFIID
Definition: guiddef.h:113
#define TRUE
Definition: types.h:120
#define E_NOINTERFACE
Definition: winerror.h:2364
static HRESULT reader_parse_externalid(xmlreader *reader)
Definition: reader.c:1821
static WCHAR * reader_get_ptr(xmlreader *reader)
Definition: reader.c:1104
strval strvalues[StringValue_Last]
Definition: reader.c:283
const GUID IID_IUnknown
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
struct attribute * attr
Definition: reader.c:277
BSTR uri
Definition: mxnamespace.c:26
static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader *iface, LPCWSTR *name, UINT *len)
Definition: reader.c:3251
static HRESULT WINAPI xmlreader_MoveToFirstAttribute(IXmlReader *iface)
Definition: reader.c:2966
static ULONG WINAPI xmlreader_Release(IXmlReader *iface)
Definition: reader.c:2735
static WCHAR get_predefined_entity(const xmlreader *reader, const strval *name)
Definition: reader.c:2034
__wchar_t WCHAR
Definition: xmlstorage.h:180
REFIID riid
Definition: precomp.h:44
XmlReaderInternalState
Definition: reader.c:32
strval prefix
Definition: reader.c:256
DtdProcessing
Definition: xmllite.idl:116
struct list attrs
Definition: reader.c:276
static void reader_pop_ns_nodes(xmlreader *reader, struct element *element)
Definition: reader.c:618
static HRESULT WINAPI xmlreader_GetBaseUri(IXmlReader *iface, LPCWSTR *baseUri, UINT *baseUri_length)
Definition: reader.c:3437
static HRESULT reader_parse_nextnode(xmlreader *reader)
Definition: reader.c:2546
const XML_Char const XML_Char * encoding
Definition: expat.h:187
uint8_t entry
Definition: isohybrid.c:63
#define WARN(fmt,...)
Definition: debug.h:111
static HRESULT reader_parse_comment(xmlreader *reader)
Definition: reader.c:1415
DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda)
IXmlReader IXmlReader_iface
Definition: reader.c:263
static HRESULT WINAPI xmlreader_GetLineNumber(IXmlReader *iface, UINT *line_number)
Definition: reader.c:3460
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
static void reader_set_current_attribute(xmlreader *reader, struct attribute *attr)
Definition: reader.c:2944
static HRESULT init_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer)
Definition: reader.c:702
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
static HRESULT reader_parse_misc(xmlreader *reader)
Definition: reader.c:1726
static WCHAR emptyW[]
Definition: reader.c:214
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
const char * wine_dbgstr_guid(const GUID *guid)
#define assert(x)
Definition: debug.h:53
IUnknown * input
Definition: reader.c:184
GLuint buffer
Definition: glext.h:5915
XmlReaderStringValue
Definition: reader.c:68
static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader *iface, LPCWSTR *name, UINT *len)
Definition: reader.c:3127
unsigned int allocated
Definition: mxwriter.c:103
unsigned int written
Definition: mxwriter.c:104
int line_number
Definition: parser.yy.c:773
static void reader_init_cstrvalue(WCHAR *str, UINT len, strval *v)
Definition: reader.c:471
static HRESULT WINAPI xmlreader_GetNamespaceUri(IXmlReader *iface, const WCHAR **uri, UINT *len)
Definition: reader.c:3195
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
static WCHAR xmlnsW[]
Definition: reader.c:216
static const char * debug_strval(const xmlreader *reader, const strval *v)
Definition: reader.c:465
UINT depth
Definition: reader.c:284
#define WCHAR
Definition: msvc.h:43
BOOL is_empty_element
Definition: reader.c:286
XmlNodeType
Definition: xmllite.idl:23
#define E_FAIL
Definition: ddrawi.h:102
Definition: send.c:47
static void readerinput_release_stream(xmlreaderinput *readerinput)
Definition: reader.c:800
unsigned int flags
Definition: reader.c:241
DWORD DWORD
Definition: winlogon.h:75
static void * heap_alloc(size_t len)
Definition: appwiz.h:61
static WCHAR * reader_get_strptr(const xmlreader *reader, const strval *v)
Definition: reader.c:336
static const char * debugstr_nodetype(XmlNodeType nodetype)
Definition: reader.c:90
HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
Definition: reader.c:3641
static void readerinput_grow(xmlreaderinput *readerinput, int length)
Definition: reader.c:853
static const strval * reader_get_value(xmlreader *reader, BOOL ensure_allocated)
Definition: reader.c:3337
static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader *iface, WCHAR *buffer, UINT chunk_size, UINT *read)
Definition: reader.c:3410
static ULONG WINAPI xmlreaderinput_Release(IXmlReaderInput *iface)
Definition: reader.c:3613
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
HRESULT WINAPI CreateXmlReaderInputWithEncodingName(IUnknown *stream, IMalloc *imalloc, LPCWSTR encoding, BOOL hint, LPCWSTR base_uri, IXmlReaderInput **ppInput)
Definition: reader.c:3684
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:271
static int readerinput_get_convlen(xmlreaderinput *readerinput)
Definition: reader.c:946
static HRESULT reader_strvaldup(xmlreader *reader, const strval *src, strval *dest)
Definition: reader.c:341
static BOOL is_wchar_space(WCHAR ch)
Definition: reader.c:1156
GLuint const GLchar * name
Definition: glext.h:6031
static void reader_update_position(xmlreader *reader, WCHAR ch)
Definition: reader.c:1130
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
GLuint n
Definition: s_context.h:57
static HRESULT reader_parse_pitarget(xmlreader *reader, strval *target)
Definition: reader.c:1597
GLuint const GLubyte GLvoid * src
Definition: s_context.h:57
static HRESULT reader_parse_endtag(xmlreader *reader)
Definition: reader.c:2349
static HRESULT reader_parse_eq(xmlreader *reader)
Definition: reader.c:1203
while(1)
Definition: macro.lex.yy.c:730
static HRESULT reader_parse_local(xmlreader *reader, strval *local, BOOL check_for_separator)
Definition: reader.c:1920
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
UINT max_depth
Definition: reader.c:285
WCHAR * baseuri
Definition: reader.c:188
GLenum GLclampf GLint i
Definition: glfuncs.h:14
static WCHAR * reader_get_ptr2(const xmlreader *reader, UINT offset)
Definition: reader.c:330
static const WCHAR ltW[]
Definition: reader.c:83
static const strval strval_xml
Definition: reader.c:218
static void reader_free_strvalue(xmlreader *reader, XmlReaderStringValue type)
Definition: reader.c:478
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
static HRESULT WINAPI xmlreader_MoveToNextAttribute(IXmlReader *iface)
Definition: reader.c:2975
#define FALSE
Definition: types.h:117
static void reader_clear_attrs(xmlreader *reader)
Definition: reader.c:398
#define CP_UTF8
Definition: nls.h:20
struct element * element
Definition: reader.c:258
static HRESULT readerinput_detectencoding(xmlreaderinput *readerinput, xml_encoding *enc)
Definition: reader.c:886
HRESULT error
Definition: reader.c:268
static int is_reader_pending(xmlreader *reader)
Definition: reader.c:697
long LONG
Definition: pedump.c:60
static int readerinput_get_utf8_convlen(xmlreaderinput *readerinput)
Definition: reader.c:928
XmlReadState state
Definition: reader.c:267
strval localname
Definition: reader.c:237
#define debugstr_w
Definition: kernel32.h:32
XmlReaderResume
Definition: reader.c:60
static size_t elem
Definition: string.c:67
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:110
IXmlResolver * resolver
Definition: reader.c:273
static PVOID ptr
Definition: dispmode.c:30
#define quote
Definition: macro.lex.yy.c:521
char * wine_dbgstr_w(const wchar_t *wstr)
Definition: CString.cpp:62
static HRESULT reader_parse_pub_literal(xmlreader *reader, strval *literal)
Definition: reader.c:1796
static const WCHAR endW[]
Definition: lex.c:53
int codepage
Definition: win_iconv.c:156
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
LONG ref
Definition: reader.c:264
static HRESULT reader_parse_chardata(xmlreader *reader)
Definition: reader.c:2440
static BOOL is_pubchar(WCHAR ch)
Definition: reader.c:1484
static const WCHAR yesW[]
Definition: htmlbody.c:594
smooth NULL
Definition: ftsmooth.c:557
static void * readerinput_realloc(xmlreaderinput *input, void *mem, size_t len)
Definition: reader.c:363
static void * reader_alloc(xmlreader *reader, size_t len)
Definition: reader.c:311
static WCHAR * readerinput_strdupW(xmlreaderinput *input, const WCHAR *str)
Definition: reader.c:373
XmlReaderProperty
Definition: xmllite.idl:124
static UINT reader_get_cur(xmlreader *reader)
Definition: reader.c:1099
static void reader_get_attribute_ns_uri(xmlreader *reader, struct attribute *attr, const WCHAR **uri, UINT *len)
Definition: reader.c:2994
struct list elements
Definition: reader.c:281
static const struct xml_encoding_data xml_encoding_map[]
Definition: reader.c:147
static HRESULT WINAPI xmlreader_SetProperty(IXmlReader *iface, UINT property, LONG_PTR value)
Definition: reader.c:2852
static XmlNodeType reader_get_nodetype(const xmlreader *reader)
Definition: reader.c:1546
static HRESULT WINAPI xmlreader_GetDepth(IXmlReader *iface, UINT *depth)
Definition: reader.c:3536
#define debugstr_guid
Definition: kernel32.h:35
strval prefix
Definition: reader.c:247
static HRESULT WINAPI xmlreader_SetInput(IXmlReader *iface, IUnknown *input)
Definition: reader.c:2756
xmlreaderinput * input
Definition: reader.c:297
static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader *iface, const WCHAR **ret, UINT *len)
Definition: reader.c:3289
static void reader_set_strvalue(xmlreader *reader, XmlReaderStringValue type, const strval *value)
Definition: reader.c:663
static void reader_mark_ns_nodes(xmlreader *reader, struct element *element)
Definition: reader.c:576
static HRESULT reader_parse_sys_literal(xmlreader *reader, strval *literal)
Definition: reader.c:1770
GLuint GLfloat * val
Definition: glext.h:7180
IMalloc * imalloc
Definition: reader.c:266
static void readerinput_free(xmlreaderinput *input, void *mem)
Definition: reader.c:368
static struct ns * reader_lookup_nsdef(xmlreader *reader)
Definition: reader.c:3187
static int strval_eq(const xmlreader *reader, const strval *str1, const strval *str2)
Definition: reader.c:492
static void reader_free(xmlreader *reader, void *mem)
Definition: reader.c:324
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
static void * m_alloc(IMalloc *imalloc, size_t len)
XmlReaderInternalState instate
Definition: reader.c:269
static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader *iface, UINT *count)
Definition: reader.c:3524
#define TRACE(s)
Definition: solgame.cpp:4
IMalloc * imalloc
Definition: reader.c:185
unsigned int BOOL
Definition: ntddk_ex.h:94
static const WCHAR noW[]
Definition: htmlbody.c:595
UINT resume[XmlReadResume_Last]
Definition: reader.c:289
static const char * debugstr_reader_prop(XmlReaderProperty prop)
Definition: reader.c:120
if(!(yy_init))
Definition: macro.lex.yy.c:704
UINT line_position
Definition: reader.c:224
struct list entry
Definition: reader.c:235
static HRESULT WINAPI xmlreader_GetProperty(IXmlReader *iface, UINT property, LONG_PTR *value)
Definition: reader.c:2815
LONG HRESULT
Definition: typedefs.h:77
static void reader_init_strvalue(UINT start, UINT len, strval *v)
Definition: reader.c:458
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
struct reader_position position
Definition: reader.c:250
static HRESULT reader_parse_xmldecl(xmlreader *reader)
Definition: reader.c:1373
UINT start
Definition: reader.c:211
static xmlreader * impl_from_IXmlReader(IXmlReader *iface)
Definition: reader.c:300
static HRESULT WINAPI xmlreaderinput_QueryInterface(IXmlReaderInput *iface, REFIID riid, void **ppvObject)
Definition: reader.c:3582
GLfloat CONST GLvector4f CONST GLfloat GLvector4f * dest
Definition: m_xform.h:122
static void reader_get_attribute_local_name(xmlreader *reader, struct attribute *attr, const WCHAR **name, UINT *len)
Definition: reader.c:3036
static const WCHAR utf8W[]
Definition: reader.c:79
GLuint GLuint GLsizei count
Definition: gl.h:1545
static void reader_pop_element(xmlreader *reader)
Definition: reader.c:643
struct list entry
Definition: reader.c:246
static void free_input_buffer(input_buffer *buffer)
Definition: reader.c:793
Definition: cookie.c:158
static const WCHAR usasciiW[]
Definition: reader.c:77
xml_encoding parse_encoding_name(const WCHAR *name, int len)
Definition: reader.c:735
BOOL prev_cr
Definition: reader.c:174
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static BOOL readerinput_is_utf8(xmlreaderinput *readerinput)
Definition: reader.c:867
static HRESULT reader_push_ns(xmlreader *reader, const strval *prefix, const strval *uri, BOOL def)
Definition: reader.c:538
GLbitfield flags
Definition: glext.h:7161
static ULONG WINAPI xmlreader_AddRef(IXmlReader *iface)
Definition: reader.c:2692
static HRESULT reader_parse_attvalue(xmlreader *reader, strval *value)
Definition: reader.c:2176
UINT attr_count
Definition: reader.c:278
static const WCHAR gtW[]
Definition: reader.c:84
static void reader_dec_depth(xmlreader *reader)
Definition: reader.c:532
static const strval strval_xmlns
Definition: reader.c:219
static HRESULT reader_parse_cdata(xmlreader *reader)
Definition: reader.c:2389
static HRESULT reader_parse_attribute(xmlreader *reader)
Definition: reader.c:2223
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
int ret
static void * m_realloc(IMalloc *imalloc, void *mem, size_t len)
static BOOL WINAPI xmlreader_IsEmptyElement(IXmlReader *iface)
Definition: reader.c:3451
const XML_Char * prefix
Definition: expat.h:380
UINT line_number
Definition: reader.c:223
static HRESULT reader_parse_reference(xmlreader *reader)
Definition: reader.c:2075
__u8 attr
Definition: mkdosfs.c:359
Definition: mxnamespace.c:23
#define InterlockedDecrement
Definition: armddk.h:52
Definition: parse.h:22
static HRESULT reader_parse_versioninfo(xmlreader *reader)
Definition: reader.c:1215
UINT len
Definition: reader.c:210
encoded_buffer encoded
Definition: reader.c:295
static void free_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer)
Definition: reader.c:717
static void reader_clear_ns(xmlreader *reader)
Definition: reader.c:2700
static HRESULT reader_move_to_first_attribute(xmlreader *reader)
Definition: reader.c:2953
static void * readerinput_alloc(xmlreaderinput *input, size_t len)
Definition: reader.c:358
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static void readerinput_shrinkraw(xmlreaderinput *readerinput, int len)
Definition: reader.c:963
ISequentialStream * stream
Definition: reader.c:192
static void reader_free_strvalues(xmlreader *reader)
Definition: reader.c:483
Definition: _list.h:228
REFIID LPVOID * ppvObject
Definition: precomp.h:44
GLenum GLsizei len
Definition: glext.h:6722
static HRESULT reader_add_attr(xmlreader *reader, strval *prefix, strval *localname, strval *qname, strval *value, const struct reader_position *position, unsigned int flags)
Definition: reader.c:414
GLsizei const GLfloat * value
Definition: glext.h:6069
static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding enc)
Definition: reader.c:1007
#define WINAPI
Definition: msvc.h:20
#define debugstr_wn
Definition: kernel32.h:33
xml_encoding get_encoding_from_codepage(UINT codepage)
Definition: reader.c:158
strval localname
Definition: reader.c:248
BSTR prefix
Definition: mxnamespace.c:25
static HRESULT WINAPI xmlreader_Read(IXmlReader *iface, XmlNodeType *nodetype)
Definition: reader.c:2891
static void m_free(IMalloc *imalloc, void *mem)
encoded_buffer utf16
Definition: reader.c:294
static HRESULT reader_inc_depth(xmlreader *reader)
Definition: reader.c:527
#define LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, list, type, field)
Definition: list.h:228
static const WCHAR commentW[]
Definition: reader.c:85
#define strcmpiW(s1, s2)
Definition: unicode.h:39
struct list ns
Definition: reader.c:280
#define local
Definition: zutil.h:30
#define ERR(fmt,...)
Definition: debug.h:109
unsigned int pending
Definition: reader.c:194
static const WCHAR publicW[]
Definition: mxwriter.c:30
static HRESULT reader_parse_pi(xmlreader *reader)
Definition: reader.c:1625
struct list entry
Definition: reader.c:255
static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader *iface)
Definition: reader.c:3096
__WINE_SERVER_LIST_INLINE int list_empty(const struct list *list)
Definition: list.h:143
#define S_OK
Definition: intsafe.h:59
static void reader_free_strvalued(xmlreader *reader, strval *v)
Definition: reader.c:389
static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *local, strval *qname)
Definition: reader.c:1962
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * get_encoding_name(xml_encoding encoding)
Definition: reader.c:153
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
#define InterlockedIncrement
Definition: armddk.h:53
GLenum GLenum GLenum input
Definition: glext.h:9031
const GLdouble * v
Definition: gl.h:2040
static HRESULT alloc_input_buffer(xmlreaderinput *input)
Definition: reader.c:764
static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader *iface, UINT *line_position)
Definition: reader.c:3492
static void reader_clear_elements(xmlreader *reader)
Definition: reader.c:498
static BOOL WINAPI xmlreader_IsEOF(IXmlReader *iface)
Definition: reader.c:3544
XmlNodeType nodetype
Definition: reader.c:271
static HRESULT reader_parse_whitespace(xmlreader *reader)
Definition: reader.c:1691
static struct element * reader_get_element(xmlreader *reader)
Definition: reader.c:450
attribute_flags
Definition: reader.c:227
GLuint start
Definition: gl.h:1545
static HRESULT WINAPI xmlreader_QueryInterface(IXmlReader *iface, REFIID riid, void **ppvObject)
Definition: reader.c:2669
struct list nsdef
Definition: reader.c:279
strval value
Definition: reader.c:239
GLsizeiptr size
Definition: glext.h:5919
IDispatch elements
static HRESULT reader_parse_versionnum(xmlreader *reader, strval *val)
Definition: reader.c:1177
#define E_NOTIMPL
Definition: ddrawi.h:99
static int reader_cmp(xmlreader *reader, const WCHAR *str)
Definition: reader.c:1112
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
strval qname
Definition: reader.c:249
static BOOL is_namechar(WCHAR ch)
Definition: reader.c:1541
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:3970
static BOOL is_wchar_encname(WCHAR ch)
Definition: reader.c:1251
static HRESULT reader_parse_content(xmlreader *reader)
Definition: reader.c:2501
static const WCHAR quoteW[]
Definition: reader.c:82
static BOOL is_char(WCHAR ch)
Definition: reader.c:1474
static struct ns * reader_lookup_ns(xmlreader *reader, const strval *prefix)
Definition: reader.c:514
static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname)
Definition: reader.c:2254
static BOOL is_namestartchar(WCHAR ch)
Definition: reader.c:1497
Definition: reader.h:83
#define MultiByteToWideChar
Definition: compat.h:100
static const WCHAR dblquoteW[]
Definition: reader.c:81
static void reader_shrink(xmlreader *reader)
Definition: reader.c:1045
input_buffer * buffer
Definition: reader.c:193
static HRESULT reader_parse_encdecl(xmlreader *reader)
Definition: reader.c:1291
static HRESULT WINAPI xmlreader_GetValue(IXmlReader *iface, const WCHAR **value, UINT *len)
Definition: reader.c:3376
static void * reader_alloc_zero(xmlreader *reader, size_t len)
Definition: reader.c:316
static const WCHAR piW[]
Definition: reader.c:86
Definition: reader.c:207
xml_encoding enc
Definition: mxwriter.c:53
struct element empty_element
Definition: reader.c:287
Definition: mem.c:156
#define LIST_FOR_EACH_ENTRY_REV(elem, list, type, field)
Definition: list.h:222
POINT cp
Definition: magnifier.c:58
Definition: name.c:23
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
static HRESULT readerinput_growraw(xmlreaderinput *readerinput)
Definition: reader.c:823
__WINE_SERVER_LIST_INLINE struct list * list_next(const struct list *list, const struct list *elem)
Definition: list.h:115
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
static HRESULT reader_parse_sddecl(xmlreader *reader)
Definition: reader.c:1329
#define c
Definition: ke_i.h:80
strval qname
Definition: reader.c:238
XmlReaderResumeState resumestate
Definition: reader.c:270
unsigned int ULONG
Definition: retypes.h:1
GLenum target
Definition: glext.h:7315
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:259
static const WCHAR systemW[]
Definition: mxwriter.c:31
static BOOL is_ncnamechar(WCHAR ch)
Definition: reader.c:1517
IUnknown * mlang
Definition: reader.c:274
xmlreaderinput * input
Definition: reader.c:265
strval uri
Definition: reader.c:257
static HRESULT readerinput_query_for_stream(xmlreaderinput *readerinput)
Definition: reader.c:810
XmlReaderResumeState
Definition: reader.c:47
static HRESULT WINAPI xmlreader_MoveToAttributeByName(IXmlReader *iface, const WCHAR *local_name, const WCHAR *namespace_uri)
Definition: reader.c:3056
static void reader_reset_parser(xmlreader *reader)
Definition: reader.c:2718
DtdProcessing dtdmode
Definition: reader.c:272
xml_encoding
Definition: mxwriter.c:34
const XML_Char const XML_Char * uri
Definition: expat.h:380
#define LIST_ENTRY(type)
Definition: queue.h:175
static HRESULT WINAPI xmlreader_GetNodeType(IXmlReader *iface, XmlNodeType *node_type)
Definition: reader.c:2931
#define E_PENDING
Definition: dinput.h:172