Removed DeflateStream.UnmanagedRead Read loop. Fixes #19313.
[mono.git] / mcs / class / System.XML / System.Xml / XmlReader.cs
1 //
2 // XmlReader.cs
3 //
4 // Authors:
5 //      Jason Diamond (jason@injektilo.org)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
8 //
9 // (C) 2001, 2002 Jason Diamond  http://injektilo.org/
10 // (c) 2002 Ximian, Inc. (http://www.ximian.com)
11 // (C) 2003 Atsushi Enomoto
12 //
13
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34 using System.Collections;
35 using System.Diagnostics;
36 using System.IO;
37 using System.Text;
38 using System.Xml.Schema; // only required for NET_2_0 (SchemaInfo)
39 using System.Xml.Serialization; // only required for NET_2_0 (SchemaInfo)
40 using Mono.Xml.Schema; // only required for NET_2_0
41 using Mono.Xml; // only required for NET_2_0
42 #if NET_4_5
43 using System.Threading;
44 using System.Threading.Tasks;
45 #endif
46
47 namespace System.Xml
48 {
49 #if NET_2_0
50         public abstract class XmlReader : IDisposable
51 #else
52         public abstract class XmlReader
53 #endif
54         {
55                 private StringBuilder readStringBuffer;
56                 private XmlReaderBinarySupport binary;
57 #if NET_2_0
58                 private XmlReaderSettings settings;
59 #endif
60
61                 #region Constructor
62
63                 protected XmlReader ()
64                 {
65                 }
66
67                 #endregion
68
69                 #region Properties
70
71                 public abstract int AttributeCount { get; }
72
73                 public abstract string BaseURI { get; }
74
75                 internal XmlReaderBinarySupport Binary {
76                         get { return binary; }
77                 }
78
79                 internal XmlReaderBinarySupport.CharGetter BinaryCharGetter {
80                         get { return binary != null ? binary.Getter : null; }
81                         set {
82                                 if (binary == null)
83                                         binary = new XmlReaderBinarySupport (this);
84                                 binary.Getter = value;
85                         }
86                 }
87
88 #if NET_2_0
89                 // To enable it internally in sys.xml, just insert these
90                 // two lines into Read():
91                 //
92                 //      #if NET_2_0
93                 //      if (Binary != null)
94                 //              Binary.Reset ();
95                 //      #endif
96                 //
97                 public virtual bool CanReadBinaryContent {
98                         get { return false; }
99                 }
100
101                 public virtual bool CanReadValueChunk {
102                         get { return false; }
103                 }
104 #else
105                 internal virtual bool CanReadBinaryContent {
106                         get { return false; }
107                 }
108
109                 internal virtual bool CanReadValueChunk {
110                         get { return false; }
111                 }
112 #endif
113
114                 public virtual bool CanResolveEntity
115                 {
116                         get     { return false; }
117                 }
118
119                 public abstract int Depth { get; }
120
121                 public abstract bool EOF { get; }
122
123                 public virtual bool HasAttributes
124                 {
125                         get { return AttributeCount > 0; }
126                 }
127
128 #if NET_4_0
129                 public virtual bool HasValue {
130                         get {
131                                 switch (NodeType) {
132                                 case XmlNodeType.Attribute:
133                                 case XmlNodeType.Comment:
134                                 case XmlNodeType.ProcessingInstruction:
135                                 case XmlNodeType.SignificantWhitespace:
136                                 case XmlNodeType.CDATA:
137                                 case XmlNodeType.Text:
138                                 case XmlNodeType.Whitespace:
139                                 case XmlNodeType.XmlDeclaration:
140                                         return true;
141                                 }
142                                 return false;
143                         }
144                 }
145 #else
146                 public abstract bool HasValue { get; }
147 #endif
148
149                 public abstract bool IsEmptyElement { get; }
150
151 #if NET_2_0
152                 public virtual bool IsDefault {
153                         get { return false; }
154                 }
155
156                 public virtual string this [int i] {
157                         get { return GetAttribute (i); }
158                 }
159
160                 public virtual string this [string name] {
161                         get { return GetAttribute (name); }
162                 }
163
164                 public virtual string this [string name, string namespaceURI] {
165                         get { return GetAttribute (name, namespaceURI); }
166                 }
167 #else
168                 public abstract bool IsDefault { get; }
169
170                 public abstract string this [int i] { get; }
171
172                 public abstract string this [string name] { get; }
173
174                 public abstract string this [string localName, string namespaceName] { get; }
175 #endif
176
177                 public abstract string LocalName { get; }
178
179 #if NET_2_0
180                 public virtual string Name {
181                         get {
182                                 return Prefix.Length > 0 ?
183                                         String.Concat (Prefix, ":", LocalName) :
184                                         LocalName;
185                         }
186                 }
187 #else
188                 public abstract string Name { get; }
189 #endif
190
191                 public abstract string NamespaceURI { get; }
192
193                 public abstract XmlNameTable NameTable { get; }
194
195                 public abstract XmlNodeType NodeType { get; }
196
197                 public abstract string Prefix { get; }
198
199 #if NET_2_0
200                 public virtual char QuoteChar {
201                         get { return '\"'; }
202                 }
203 #else
204                 public abstract char QuoteChar { get; }
205 #endif
206
207                 public abstract ReadState ReadState { get; }
208
209 #if NET_2_0
210                 public virtual IXmlSchemaInfo SchemaInfo {
211                         get { return null; }
212                 }
213
214                 public virtual XmlReaderSettings Settings {
215                         get { return settings; }
216                 }
217 #endif
218
219                 public abstract string Value { get; }
220
221 #if NET_2_0
222                 public virtual string XmlLang {
223                         get { return String.Empty; }
224                 }
225
226                 public virtual XmlSpace XmlSpace {
227                         get { return XmlSpace.None; }
228                 }
229 #else
230                 public abstract string XmlLang { get; }
231
232                 public abstract XmlSpace XmlSpace { get; }
233 #endif
234
235                 #endregion
236
237                 #region Methods
238
239 #if NET_4_5
240                 public virtual void Close ()
241                 {
242                         if (asyncRunning)
243                                 throw new InvalidOperationException ("An asynchronous operation is already in progress.");
244                 }
245 #else
246                 public abstract void Close ();
247 #endif
248
249 #if NET_2_0
250                 private static XmlNameTable PopulateNameTable (
251                         XmlReaderSettings settings)
252                 {
253                         XmlNameTable nameTable = settings.NameTable;
254                         if (nameTable == null)
255                                 nameTable = new NameTable ();
256                         return nameTable;
257                 }
258
259                 private static XmlParserContext PopulateParserContext (
260                         XmlReaderSettings settings, string baseUri)
261                 {
262                         XmlNameTable nt = PopulateNameTable (settings);
263                         return new XmlParserContext (nt,
264                                 new XmlNamespaceManager (nt),
265                                 null,
266                                 null,
267                                 null,
268                                 null,
269                                 baseUri,
270                                 null,
271                                 XmlSpace.None,
272                                 null);
273                 }
274
275                 private static XmlNodeType GetNodeType (
276                         XmlReaderSettings settings)
277                 {
278                         ConformanceLevel level = settings != null ? settings.ConformanceLevel : ConformanceLevel.Auto;
279                         return
280                                 level == ConformanceLevel.Fragment ?
281                                 XmlNodeType.Element :
282                                 XmlNodeType.Document;
283                 }
284
285                 public static XmlReader Create (Stream input)
286                 {
287                         return Create (input, null);
288                 }
289
290                 public static XmlReader Create (string inputUri)
291                 {
292                         return Create (inputUri, null);
293                 }
294
295                 public static XmlReader Create (TextReader input)
296                 {
297                         return Create (input, null);
298                 }
299
300                 public static XmlReader Create (string inputUri, XmlReaderSettings settings)
301                 {
302                         return Create (inputUri, settings, null);
303                 }
304
305                 public static XmlReader Create (Stream input, XmlReaderSettings settings)
306                 {
307                         return Create (input, settings, String.Empty);
308                 }
309
310                 public static XmlReader Create (TextReader input, XmlReaderSettings settings)
311                 {
312                         return Create (input, settings, String.Empty);
313                 }
314
315                 static XmlReaderSettings PopulateSettings (XmlReaderSettings src)
316                 {
317                         XmlReaderSettings copy;
318                         if (src == null)
319                                 copy = new XmlReaderSettings ();
320                         else
321                                 copy = src.Clone ();
322 #if NET_4_5
323                         copy.SetReadOnly ();
324 #endif
325                         return copy;
326                 }
327
328                 static XmlReaderSettings PopulateSettings (XmlReader reader, XmlReaderSettings src)
329                 {
330                         XmlReaderSettings copy;
331                         if (src == null)
332                                 copy = new XmlReaderSettings ();
333                         else
334                                 copy = src.Clone ();
335 #if NET_4_5
336                         if (reader.Settings != null)
337                                 copy.Async = reader.Settings.Async;
338                         copy.SetReadOnly ();
339 #endif
340                         return copy;
341                 }
342
343                 public static XmlReader Create (Stream input, XmlReaderSettings settings, string baseUri)
344                 {
345                         settings = PopulateSettings (settings);
346                         return Create (input, settings,
347                                 PopulateParserContext (settings, baseUri));
348                 }
349
350                 public static XmlReader Create (TextReader input, XmlReaderSettings settings, string baseUri)
351                 {
352                         settings = PopulateSettings (settings);
353                         return Create (input, settings,
354                                 PopulateParserContext (settings, baseUri));
355                 }
356
357                 public static XmlReader Create (XmlReader reader, XmlReaderSettings settings)
358                 {
359                         settings = PopulateSettings (reader, settings);
360                         XmlReader r = CreateFilteredXmlReader (reader, settings);
361                         r.settings = settings;
362                         return r;
363                 }
364
365                 public static XmlReader Create (string inputUri, XmlReaderSettings settings, XmlParserContext inputContext)
366                 {
367                         settings = PopulateSettings (settings);
368                         bool closeInputBak = settings.CloseInput;
369                         try {
370                                 settings.CloseInput = true; // forced. See XmlReaderCommonTests.CreateFromUrlClose().
371                                 if (inputContext == null)
372                                         inputContext = PopulateParserContext (settings, inputUri);
373                                 XmlTextReader xtr = new XmlTextReader (false, settings.XmlResolver, inputUri, GetNodeType (settings), inputContext);
374                                 XmlReader ret = CreateCustomizedTextReader (xtr, settings);
375                                 return ret;
376                         } finally {
377                                 settings.CloseInput = closeInputBak;
378                         }
379                 }
380
381                 public static XmlReader Create (Stream input, XmlReaderSettings settings, XmlParserContext inputContext)
382                 {
383                         settings = PopulateSettings (settings);
384                         if (inputContext == null)
385                                 inputContext = PopulateParserContext (settings, String.Empty);
386                         return CreateCustomizedTextReader (new XmlTextReader (input, GetNodeType (settings), inputContext), settings);
387                 }
388
389                 public static XmlReader Create (TextReader input, XmlReaderSettings settings, XmlParserContext inputContext)
390                 {
391                         settings = PopulateSettings (settings);
392                         if (inputContext == null)
393                                 inputContext = PopulateParserContext (settings, String.Empty);
394                         return CreateCustomizedTextReader (new XmlTextReader (inputContext.BaseURI, input, GetNodeType (settings), inputContext), settings);
395                 }
396
397                 private static XmlReader CreateCustomizedTextReader (XmlTextReader reader, XmlReaderSettings settings)
398                 {
399                         reader.XmlResolver = settings.XmlResolver;
400                         // Normalization is set true by default.
401                         reader.Normalization = true;
402                         reader.EntityHandling = EntityHandling.ExpandEntities;
403
404                         if (settings.ProhibitDtd)
405                                 reader.ProhibitDtd = true;
406
407                         if (!settings.CheckCharacters)
408                                 reader.CharacterChecking = false;
409
410                         // I guess it might be changed in 2.0 RTM to set true
411                         // as default, or just disappear. It goes against
412                         // XmlTextReader's default usage and users will have 
413                         // to close input manually (that's annoying). Moreover,
414                         // MS XmlTextReader consumes text input more than 
415                         // actually read and users can acquire those extra
416                         // consumption by GetRemainder() that returns different
417                         // TextReader.
418                         reader.CloseInput = settings.CloseInput;
419
420                         // I would like to support it in detail later;
421                         // MSDN description looks source of confusion. We don't
422                         // need examples, but precise list of how it works.
423                         reader.Conformance = settings.ConformanceLevel;
424
425                         reader.AdjustLineInfoOffset (settings.LineNumberOffset,
426                                 settings.LinePositionOffset);
427
428                         if (settings.NameTable != null)
429                                 reader.SetNameTable (settings.NameTable);
430
431                         XmlReader r = CreateFilteredXmlReader (reader, settings);
432                         r.settings = settings;
433                         return r;
434                 }
435
436                 private static XmlReader CreateFilteredXmlReader (XmlReader reader, XmlReaderSettings settings)
437                 {
438                         ConformanceLevel conf = ConformanceLevel.Auto;
439                         if (reader is XmlTextReader)
440                                 conf = ((XmlTextReader) reader).Conformance;
441                         else if (reader.Settings != null)
442                                 conf = reader.Settings.ConformanceLevel;
443                         else
444                                 conf = settings.ConformanceLevel;
445                         if (settings.ConformanceLevel != ConformanceLevel.Auto &&
446                                 conf != settings.ConformanceLevel)
447                                 throw new InvalidOperationException (String.Format ("ConformanceLevel cannot be overwritten by a wrapping XmlReader. The source reader has {0}, while {1} is specified.", conf, settings.ConformanceLevel));
448                         settings.ConformanceLevel = conf;
449
450                         reader = CreateValidatingXmlReader (reader, settings);
451
452                         if ( settings.IgnoreComments ||
453                              settings.IgnoreProcessingInstructions ||
454                              settings.IgnoreWhitespace)
455                                 return new XmlFilterReader (reader, settings);
456                         else {
457                                 reader.settings = settings;
458                                 return reader;
459                         }
460                 }
461
462                 private static XmlReader CreateValidatingXmlReader (XmlReader reader, XmlReaderSettings settings)
463                 {
464                         XmlValidatingReader xvr = null;
465                         switch (settings.ValidationType) {
466                         // Auto and XDR are obsoleted in 2.0 and therefore ignored.
467                         default:
468                                 return reader;
469                         case ValidationType.DTD:
470                                 xvr = new XmlValidatingReader (reader);
471                                 xvr.XmlResolver = settings.XmlResolver;
472                                 xvr.ValidationType = ValidationType.DTD;
473                                 break;
474                         case ValidationType.Schema:
475                                 return new XmlSchemaValidatingReader (reader, settings);
476                         }
477
478                         // Actually I don't think they are treated in DTD validation though...
479                         if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessIdentityConstraints) == 0)
480                                 throw new NotImplementedException ();
481                         //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessInlineSchema) != 0)
482                         //      throw new NotImplementedException ();
483                         //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessSchemaLocation) != 0)
484                         //      throw new NotImplementedException ();
485                         //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ReportValidationWarnings) == 0)
486                         //      throw new NotImplementedException ();
487
488                         return xvr != null ? xvr : reader;
489                 }
490
491 #if NET_4_0
492                 public void Dispose ()
493 #else
494                 void IDisposable.Dispose() 
495 #endif
496                 {
497                         Dispose (false);
498                 }
499
500                 protected virtual void Dispose (bool disposing)
501                 {
502                         if (ReadState != ReadState.Closed)
503                                 Close ();
504                 }
505 #endif
506
507                 public abstract string GetAttribute (int i);
508
509                 public abstract string GetAttribute (string name);
510
511                 public abstract string GetAttribute (string name, string namespaceURI);
512
513                 public static bool IsName (string str)
514                 {
515                         return str != null && XmlChar.IsName (str);
516                 }
517
518                 public static bool IsNameToken (string str)
519                 {
520                         return str != null && XmlChar.IsNmToken (str);
521                 }
522
523                 public virtual bool IsStartElement ()
524                 {
525                         return (MoveToContent () == XmlNodeType.Element);
526                 }
527
528                 public virtual bool IsStartElement (string name)
529                 {
530                         if (!IsStartElement ())
531                                 return false;
532
533                         return (Name == name);
534                 }
535
536                 public virtual bool IsStartElement (string localname, string ns)
537                 {
538                         if (!IsStartElement ())
539                                 return false;
540
541                         return (LocalName == localname && NamespaceURI == ns);
542                 }
543
544                 public abstract string LookupNamespace (string prefix);
545
546 #if NET_2_0
547                 public virtual void MoveToAttribute (int i)
548                 {
549                         if (i >= AttributeCount)
550                                 throw new ArgumentOutOfRangeException ();
551                         MoveToFirstAttribute ();
552                         for (int a = 0; a < i; a++)
553                                 MoveToNextAttribute ();
554                 }
555 #else
556                 public abstract void MoveToAttribute (int i);
557 #endif
558
559                 public abstract bool MoveToAttribute (string name);
560
561                 public abstract bool MoveToAttribute (string name, string ns);
562
563                 private bool IsContent (XmlNodeType nodeType)
564                 {
565                         /* MS doc says:
566                          * (non-white space text, CDATA, Element, EndElement, EntityReference, or EndEntity)
567                          */
568                         switch (nodeType) {
569                         case XmlNodeType.Text:
570                                 return true;
571                         case XmlNodeType.CDATA:
572                                 return true;
573                         case XmlNodeType.Element:
574                                 return true;
575                         case XmlNodeType.EndElement:
576                                 return true;
577                         case XmlNodeType.EntityReference:
578                                 return true;
579                         case XmlNodeType.EndEntity:
580                                 return true;
581                         }
582
583                         return false;
584                 }
585
586                 public virtual XmlNodeType MoveToContent ()
587                 {
588                         switch (ReadState) {
589                         case ReadState.Initial:
590                         case ReadState.Interactive:
591                                 break;
592                         default:
593                                 return NodeType;
594                         }
595
596                         if (NodeType == XmlNodeType.Attribute)
597                                 MoveToElement ();
598
599                         do {
600                                 if (IsContent (NodeType))
601                                         return NodeType;
602                                 Read ();
603                         } while (!EOF);
604                         return XmlNodeType.None;
605                 }
606
607                 public abstract bool MoveToElement ();
608
609                 public abstract bool MoveToFirstAttribute ();
610
611                 public abstract bool MoveToNextAttribute ();
612
613                 public abstract bool Read ();
614
615                 public abstract bool ReadAttributeValue ();
616
617                 public virtual string ReadElementString ()
618                 {
619                         if (MoveToContent () != XmlNodeType.Element) {
620                                 string error = String.Format ("'{0}' is an invalid node type.",
621                                                               NodeType.ToString ());
622                                 throw XmlError (error);
623                         }
624
625                         string result = String.Empty;
626                         if (!IsEmptyElement) {
627                                 Read ();
628                                 result = ReadString ();
629                                 if (NodeType != XmlNodeType.EndElement) {
630                                         string error = String.Format ("'{0}' is an invalid node type.",
631                                                                       NodeType.ToString ());
632                                         throw XmlError (error);
633                                 }
634                         }
635
636                         Read ();
637                         return result;
638                 }
639
640                 public virtual string ReadElementString (string name)
641                 {
642                         if (MoveToContent () != XmlNodeType.Element) {
643                                 string error = String.Format ("'{0}' is an invalid node type.",
644                                                               NodeType.ToString ());
645                                 throw XmlError (error);
646                         }
647
648                         if (name != Name) {
649                                 string error = String.Format ("The {0} tag from namespace {1} is expected.",
650                                                               Name, NamespaceURI);
651                                 throw XmlError (error);
652                         }
653
654                         string result = String.Empty;
655                         if (!IsEmptyElement) {
656                                 Read ();
657                                 result = ReadString ();
658                                 if (NodeType != XmlNodeType.EndElement) {
659                                         string error = String.Format ("'{0}' is an invalid node type.",
660                                                                       NodeType.ToString ());
661                                         throw XmlError (error);
662                                 }
663                         }
664
665                         Read ();
666                         return result;
667                 }
668
669                 public virtual string ReadElementString (string localname, string ns)
670                 {
671                         if (MoveToContent () != XmlNodeType.Element) {
672                                 string error = String.Format ("'{0}' is an invalid node type.",
673                                                               NodeType.ToString ());
674                                 throw XmlError (error);
675                         }
676
677                         if (localname != LocalName || NamespaceURI != ns) {
678                                 string error = String.Format ("The {0} tag from namespace {1} is expected.",
679                                                               LocalName, NamespaceURI);
680                                 throw XmlError (error);
681                         }
682
683                         string result = String.Empty;
684                         if (!IsEmptyElement) {
685                                 Read ();
686                                 result = ReadString ();
687                                 if (NodeType != XmlNodeType.EndElement) {
688                                         string error = String.Format ("'{0}' is an invalid node type.",
689                                                                       NodeType.ToString ());
690                                         throw XmlError (error);
691                                 }
692                         }
693
694                         Read ();
695                         return result;
696                 }
697
698                 public virtual void ReadEndElement ()
699                 {
700                         if (MoveToContent () != XmlNodeType.EndElement) {
701                                 string error = String.Format ("'{0}' is an invalid node type.",
702                                                               NodeType.ToString ());
703                                 throw XmlError (error);
704                         }
705
706                         Read ();
707                 }
708
709                 public virtual string ReadInnerXml ()
710                 {
711                         if (ReadState != ReadState.Interactive || NodeType == XmlNodeType.EndElement)
712                                 return String.Empty;
713
714                         if (IsEmptyElement) {
715                                 Read ();
716                                 return String.Empty;
717                         }
718                         StringWriter sw = new StringWriter ();
719                         XmlTextWriter xtw = new XmlTextWriter (sw);
720                         if (NodeType == XmlNodeType.Element) {
721                                 int startDepth = Depth;
722                                 Read ();
723                                 while (startDepth < Depth) {
724                                         if (ReadState != ReadState.Interactive)
725                                                 throw XmlError ("Unexpected end of the XML reader.");
726                                         xtw.WriteNode (this, false);
727                                 }
728                                 // reader is now end element, then proceed once more.
729                                 Read ();
730                         }
731                         else
732                                 xtw.WriteNode (this, false);
733
734                         return sw.ToString ();
735                 }
736
737                 public virtual string ReadOuterXml ()
738                 {
739                         if (ReadState != ReadState.Interactive || NodeType == XmlNodeType.EndElement)
740                                 return String.Empty;
741
742                         switch (NodeType) {
743                         case XmlNodeType.Element:
744                         case XmlNodeType.Attribute:
745                                 StringWriter sw = new StringWriter ();
746                                 XmlTextWriter xtw = new XmlTextWriter (sw);
747                                 xtw.WriteNode (this, false);
748                                 return sw.ToString ();
749                         default:
750                                 Skip ();
751                                 return String.Empty;
752                         }
753                 }
754
755                 public virtual void ReadStartElement ()
756                 {
757                         if (MoveToContent () != XmlNodeType.Element) {
758                                 string error = String.Format ("'{0}' is an invalid node type.",
759                                                               NodeType.ToString ());
760                                 throw XmlError (error);
761                         }
762
763                         Read ();
764                 }
765
766                 public virtual void ReadStartElement (string name)
767                 {
768                         if (MoveToContent () != XmlNodeType.Element) {
769                                 string error = String.Format ("'{0}' is an invalid node type.",
770                                                               NodeType.ToString ());
771                                 throw XmlError (error);
772                         }
773
774                         if (name != Name) {
775                                 string error = String.Format ("The {0} tag from namespace {1} is expected.",
776                                                               Name, NamespaceURI);
777                                 throw XmlError (error);
778                         }
779
780                         Read ();
781                 }
782
783                 public virtual void ReadStartElement (string localname, string ns)
784                 {
785                         if (MoveToContent () != XmlNodeType.Element) {
786                                 string error = String.Format ("'{0}' is an invalid node type.",
787                                                               NodeType.ToString ());
788                                 throw XmlError (error);
789                         }
790
791                         if (localname != LocalName || NamespaceURI != ns) {
792                                 string error = String.Format ("Expecting {0} tag from namespace {1}, got {2} and {3} instead",
793                                                               localname, ns,
794                                                               LocalName, NamespaceURI);
795                                 throw XmlError (error);
796                         }
797
798                         Read ();
799                 }
800
801                 public virtual string ReadString ()
802                 {
803                         if (readStringBuffer == null)
804                                 readStringBuffer = new StringBuilder ();
805                         readStringBuffer.Length = 0;
806
807                         MoveToElement ();
808
809                         switch (NodeType) {
810                         default:
811                                 return String.Empty;
812                         case XmlNodeType.Element:
813                                 if (IsEmptyElement)
814                                         return String.Empty;
815                                 do {
816                                         Read ();
817                                         switch (NodeType) {
818                                         case XmlNodeType.Text:
819                                         case XmlNodeType.CDATA:
820                                         case XmlNodeType.Whitespace:
821                                         case XmlNodeType.SignificantWhitespace:
822                                                 readStringBuffer.Append (Value);
823                                                 continue;
824                                         }
825                                         break;
826                                 } while (true);
827                                 break;
828                         case XmlNodeType.Text:
829                         case XmlNodeType.CDATA:
830                         case XmlNodeType.Whitespace:
831                         case XmlNodeType.SignificantWhitespace:
832                                 do {
833                                         switch (NodeType) {
834                                         case XmlNodeType.Text:
835                                         case XmlNodeType.CDATA:
836                                         case XmlNodeType.Whitespace:
837                                         case XmlNodeType.SignificantWhitespace:
838                                                 readStringBuffer.Append (Value);
839                                                 Read ();
840                                                 continue;
841                                         }
842                                         break;
843                                 } while (true);
844                                 break;
845                         }
846                         string ret = readStringBuffer.ToString ();
847                         readStringBuffer.Length = 0;
848                         return ret;
849                 }
850
851 #if NET_2_0
852                 public virtual Type ValueType {
853                         get { return typeof (string); }
854                 }
855
856                 public virtual bool ReadToDescendant (string name)
857                 {
858                         if (ReadState == ReadState.Initial) {
859                                 MoveToContent ();
860                                 if (IsStartElement (name))
861                                         return true;
862                         }
863                         if (NodeType != XmlNodeType.Element || IsEmptyElement)
864                                 return false;
865                         int depth = Depth;
866                         for (Read (); depth < Depth; Read ())
867                                 if (NodeType == XmlNodeType.Element && name == Name)
868                                         return true;
869                         return false;
870                 }
871
872                 public virtual bool ReadToDescendant (string localName, string namespaceURI)
873                 {
874                         if (ReadState == ReadState.Initial) {
875                                 MoveToContent ();
876                                 if (IsStartElement (localName, namespaceURI))
877                                         return true;
878                         }
879                         if (NodeType != XmlNodeType.Element || IsEmptyElement)
880                                 return false;
881                         int depth = Depth;
882                         for (Read (); depth < Depth; Read ())
883                                 if (NodeType == XmlNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
884                                         return true;
885                         return false;
886                 }
887
888                 public virtual bool ReadToFollowing (string name)
889                 {
890                         while (Read ())
891                                 if (NodeType == XmlNodeType.Element && name == Name)
892                                         return true;
893                         return false;
894                 }
895
896                 public virtual bool ReadToFollowing (string localName, string namespaceURI)
897                 {
898                         while (Read ())
899                                 if (NodeType == XmlNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
900                                         return true;
901                         return false;
902                 }
903
904                 public virtual bool ReadToNextSibling (string name)
905                 {
906                         if (ReadState != ReadState.Interactive)
907                                 return false;
908                         MoveToElement ();
909                         int depth = Depth;
910                         Skip ();
911                         for (; !EOF && depth <= Depth; Skip ())
912                                 if (NodeType == XmlNodeType.Element && name == Name)
913                                         return true;
914                         return false;
915                 }
916
917                 public virtual bool ReadToNextSibling (string localName, string namespaceURI)
918                 {
919                         if (ReadState != ReadState.Interactive)
920                                 return false;
921                         int depth = Depth;
922                         Skip ();
923                         for (; !EOF && depth <= Depth; Skip ())
924                                 if (NodeType == XmlNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
925                                         return true;
926                         return false;
927                 }
928
929                 public virtual XmlReader ReadSubtree ()
930                 {
931                         if (NodeType != XmlNodeType.Element)
932                                 throw new InvalidOperationException (String.Format ("ReadSubtree() can be invoked only when the reader is positioned on an element. Current node is {0}. {1}", NodeType, GetLocation ()));
933                         return new SubtreeXmlReader (this);
934                 }
935
936                 private string ReadContentString ()
937                 {
938                         // The latter condition indicates that this XmlReader is on an attribute value
939                         // (HasAttributes is to indicate it is on attribute value).
940                         if (NodeType == XmlNodeType.Attribute || NodeType != XmlNodeType.Element && HasAttributes)
941                                 return Value;
942                         return ReadContentString (true);
943                 }
944
945                 private string ReadContentString (bool isText)
946                 {
947                         if (isText) {
948                                 switch (NodeType) {
949                                 case XmlNodeType.Text:
950                                 case XmlNodeType.SignificantWhitespace:
951                                 case XmlNodeType.Whitespace:
952                                 case XmlNodeType.CDATA:
953                                         break;
954                                 case XmlNodeType.Element:
955                                         throw new InvalidOperationException (String.Format ("Node type {0} is not supported in this operation.{1}", NodeType, GetLocation ()));
956                                 default:
957                                         return String.Empty;
958                                 }
959                         }
960
961                         string value = String.Empty;
962                         do {
963                                 switch (NodeType) {
964                                 case XmlNodeType.Element:
965                                         if (isText)
966                                                 return value;
967                                         throw XmlError ("Child element is not expected in this operation.");
968                                 case XmlNodeType.EndElement:
969                                         return value;
970                                 case XmlNodeType.Text:
971                                 case XmlNodeType.CDATA:
972                                 case XmlNodeType.SignificantWhitespace:
973                                 case XmlNodeType.Whitespace:
974                                         value += Value;
975                                         break;
976                                 }
977                         } while (Read ());
978                         throw XmlError ("Unexpected end of document.");
979                 }
980
981                 string GetLocation ()
982                 {
983                         IXmlLineInfo li = this as IXmlLineInfo;
984                         return li != null && li.HasLineInfo () ?
985                                 String.Format (" {0} (line {1}, column {2})", BaseURI, li.LineNumber, li.LinePosition) : String.Empty;
986                 }
987
988                 [MonoTODO]
989                 public virtual object ReadElementContentAsObject ()
990                 {
991                         return ReadElementContentAs (ValueType, null);
992                 }
993
994                 [MonoTODO]
995                 public virtual object ReadElementContentAsObject (string localName, string namespaceURI)
996                 {
997                         return ReadElementContentAs (ValueType, null, localName, namespaceURI);
998                 }
999
1000                 [MonoTODO]
1001                 public virtual object ReadContentAsObject ()
1002                 {
1003                         return ReadContentAs (ValueType, null);
1004                 }
1005
1006 #if NET_4_5
1007                 public virtual DateTimeOffset ReadContentAsDateTimeOffset ()
1008                 {
1009                         try {
1010                                 return XmlConvert.ToDateTimeOffset (ReadContentString ());
1011                         } catch (Exception e) {
1012                                 throw XmlError ("Typed value is invalid.", e);
1013                         }
1014                 }
1015 #endif
1016
1017                 public virtual object ReadElementContentAs (Type returnType, IXmlNamespaceResolver namespaceResolver)
1018                 {
1019                         bool isEmpty = IsEmptyElement;
1020                         ReadStartElement ();
1021                         object obj = ValueAs (isEmpty ? String.Empty : ReadContentString (false), returnType, namespaceResolver, false);
1022                         if (!isEmpty)
1023                                 ReadEndElement ();
1024                         return obj;
1025                 }
1026
1027                 public virtual object ReadElementContentAs (Type returnType, IXmlNamespaceResolver namespaceResolver, string localName, string namespaceURI)
1028                 {
1029                         if (localName == null)
1030                                 throw new ArgumentNullException ("localName");
1031                         if (namespaceURI == null)
1032                                 throw new ArgumentNullException ("namespaceURI");
1033
1034                         bool isEmpty = IsEmptyElement;
1035                         ReadStartElement (localName, namespaceURI);
1036                         if (isEmpty)
1037                                 return ValueAs (String.Empty, returnType, namespaceResolver, false);
1038                         object obj = ReadContentAs (returnType, namespaceResolver);
1039                         ReadEndElement ();
1040                         return obj;
1041                 }
1042
1043                 public virtual object ReadContentAs (Type returnType, IXmlNamespaceResolver namespaceResolver)
1044                 {
1045                         return ValueAs (ReadContentString (), returnType, namespaceResolver, false);
1046                 }
1047
1048                 private object ValueAs (string text, Type type, IXmlNamespaceResolver resolver, bool isArrayItem)
1049                 {
1050                         try {
1051                                 if (type == typeof (object))
1052                                         return text;
1053                                 if (type.IsArray && !isArrayItem) {
1054                                         var elemType = type.GetElementType ();
1055                                         var sarr = text.Split ((string []) null, StringSplitOptions.RemoveEmptyEntries);
1056                                         var ret = Array.CreateInstance (elemType, sarr.Length);
1057                                         for (int i = 0; i < ret.Length; i++)
1058                                                 ret.SetValue (ValueAs (sarr [i], elemType, resolver, true), i);
1059                                         return ret;
1060                                 }
1061
1062                                 if (type == typeof (XmlQualifiedName)) {
1063                                         if (resolver != null)
1064                                                 return XmlQualifiedName.Parse (text, resolver, true);
1065                                         else
1066                                                 return XmlQualifiedName.Parse (text, this, true);
1067                                 }
1068                                 if (type == typeof (Uri))
1069                                         return XmlConvert.ToUri (text);
1070                                 if (type == typeof (TimeSpan))
1071                                         return XmlConvert.ToTimeSpan (text);
1072                                 if (type == typeof (DateTimeOffset))
1073                                         return XmlConvert.ToDateTimeOffset (text);
1074
1075                                 switch (Type.GetTypeCode (type)) {
1076                                 case TypeCode.Boolean:
1077                                         return XQueryConvert.StringToBoolean (text);
1078                                 case TypeCode.Byte:
1079                                         return XmlConvert.ToByte (text);
1080                                 case TypeCode.SByte:
1081                                         return XmlConvert.ToSByte (text);
1082                                 case TypeCode.Int16:
1083                                         return XmlConvert.ToInt16 (text);
1084                                 case TypeCode.UInt16:
1085                                         return XQueryConvert.StringToUnsignedShort (text);
1086                                 case TypeCode.Int32:
1087                                         return XQueryConvert.StringToInt (text);
1088                                 case TypeCode.UInt32:
1089                                         return XQueryConvert.StringToUnsignedInt (text);
1090                                 case TypeCode.Int64:
1091                                         return XQueryConvert.StringToInteger (text);
1092                                 case TypeCode.UInt64:
1093                                         return XQueryConvert.StringToUnsignedLong (text);
1094                                 case TypeCode.DateTime:
1095                                         return XQueryConvert.StringToDateTime (text);
1096                                 case TypeCode.Decimal:
1097                                         return XQueryConvert.StringToDecimal (text);
1098                                 case TypeCode.Double:
1099                                         return XQueryConvert.StringToDouble (text);
1100                                 case TypeCode.Single:
1101                                         return XQueryConvert.StringToFloat (text);
1102                                 case TypeCode.String:
1103                                         return text;
1104                                 }
1105                         } catch (Exception ex) {
1106                                 throw XmlError (String.Format ("Current text value '{0}' is not acceptable for specified type '{1}'. {2}", text, type, ex != null ? ex.Message : String.Empty), ex);
1107                         }
1108                         throw new XmlException (String.Format ("Specified type '{0}' is not supported.", type));
1109                 }
1110
1111                 public virtual bool ReadElementContentAsBoolean ()
1112                 {
1113                         try {
1114                                 return XQueryConvert.StringToBoolean (ReadElementContentAsString ());
1115                         } catch (FormatException ex) {
1116                                 throw XmlError ("Typed value is invalid.", ex);
1117                         }
1118                 }
1119
1120                 public virtual DateTime ReadElementContentAsDateTime ()
1121                 {
1122                         try {
1123                                 return XQueryConvert.StringToDateTime (ReadElementContentAsString ());
1124                         } catch (FormatException ex) {
1125                                 throw XmlError ("Typed value is invalid.", ex);
1126                         }
1127                 }
1128
1129                 public virtual decimal ReadElementContentAsDecimal ()
1130                 {
1131                         try {
1132                                 return XQueryConvert.StringToDecimal (ReadElementContentAsString ());
1133                         } catch (FormatException ex) {
1134                                 throw XmlError ("Typed value is invalid.", ex);
1135                         }
1136                 }
1137
1138                 public virtual double ReadElementContentAsDouble ()
1139                 {
1140                         try {
1141                                 return XQueryConvert.StringToDouble (ReadElementContentAsString ());
1142                         } catch (FormatException ex) {
1143                                 throw XmlError ("Typed value is invalid.", ex);
1144                         }
1145                 }
1146
1147                 public virtual float ReadElementContentAsFloat ()
1148                 {
1149                         try {
1150                                 return XQueryConvert.StringToFloat (ReadElementContentAsString ());
1151                         } catch (FormatException ex) {
1152                                 throw XmlError ("Typed value is invalid.", ex);
1153                         }
1154                 }
1155
1156                 public virtual int ReadElementContentAsInt ()
1157                 {
1158                         try {
1159                                 return XQueryConvert.StringToInt (ReadElementContentAsString ());
1160                         } catch (FormatException ex) {
1161                                 throw XmlError ("Typed value is invalid.", ex);
1162                         }
1163                 }
1164
1165                 public virtual long ReadElementContentAsLong ()
1166                 {
1167                         try {
1168                                 return XQueryConvert.StringToInteger (ReadElementContentAsString ());
1169                         } catch (FormatException ex) {
1170                                 throw XmlError ("Typed value is invalid.", ex);
1171                         }
1172                 }
1173
1174                 public virtual string ReadElementContentAsString ()
1175                 {
1176                         bool isEmpty = IsEmptyElement;
1177                         // unlike ReadStartElement() it rejects non-content nodes (this check is done before MoveToContent())
1178                         if (NodeType != XmlNodeType.Element)
1179                                 throw new InvalidOperationException (String.Format ("'{0}' is an element node.", NodeType));
1180                         ReadStartElement ();
1181                         if (isEmpty)
1182                                 return String.Empty;
1183                         string s = ReadContentString (false);
1184                         ReadEndElement ();
1185                         return s;
1186                 }
1187
1188                 public virtual bool ReadElementContentAsBoolean (string localName, string namespaceURI)
1189                 {
1190                         try {
1191                                 return XQueryConvert.StringToBoolean (ReadElementContentAsString (localName, namespaceURI));
1192                         } catch (FormatException ex) {
1193                                 throw XmlError ("Typed value is invalid.", ex);
1194                         }
1195                 }
1196
1197                 public virtual DateTime ReadElementContentAsDateTime (string localName, string namespaceURI)
1198                 {
1199                         try {
1200                                 return XQueryConvert.StringToDateTime (ReadElementContentAsString (localName, namespaceURI));
1201                         } catch (FormatException ex) {
1202                                 throw XmlError ("Typed value is invalid.", ex);
1203                         }
1204                 }
1205
1206                 public virtual decimal ReadElementContentAsDecimal (string localName, string namespaceURI)
1207                 {
1208                         try {
1209                                 return XQueryConvert.StringToDecimal (ReadElementContentAsString (localName, namespaceURI));
1210                         } catch (FormatException ex) {
1211                                 throw XmlError ("Typed value is invalid.", ex);
1212                         }
1213                 }
1214
1215                 public virtual double ReadElementContentAsDouble (string localName, string namespaceURI)
1216                 {
1217                         try {
1218                                 return XQueryConvert.StringToDouble (ReadElementContentAsString (localName, namespaceURI));
1219                         } catch (FormatException ex) {
1220                                 throw XmlError ("Typed value is invalid.", ex);
1221                         }
1222                 }
1223
1224                 public virtual float ReadElementContentAsFloat (string localName, string namespaceURI)
1225                 {
1226                         try {
1227                                 return XQueryConvert.StringToFloat (ReadElementContentAsString (localName, namespaceURI));
1228                         } catch (FormatException ex) {
1229                                 throw XmlError ("Typed value is invalid.", ex);
1230                         }
1231                 }
1232
1233                 public virtual int ReadElementContentAsInt (string localName, string namespaceURI)
1234                 {
1235                         try {
1236                                 return XQueryConvert.StringToInt (ReadElementContentAsString (localName, namespaceURI));
1237                         } catch (FormatException ex) {
1238                                 throw XmlError ("Typed value is invalid.", ex);
1239                         }
1240                 }
1241
1242                 public virtual long ReadElementContentAsLong (string localName, string namespaceURI)
1243                 {
1244                         try {
1245                                 return XQueryConvert.StringToInteger (ReadElementContentAsString (localName, namespaceURI));
1246                         } catch (FormatException ex) {
1247                                 throw XmlError ("Typed value is invalid.", ex);
1248                         }
1249                 }
1250
1251                 public virtual string ReadElementContentAsString (string localName, string namespaceURI)
1252                 {
1253                         bool isEmpty = IsEmptyElement;
1254                         // unlike ReadStartElement() it rejects non-content nodes (this check is done before MoveToContent())
1255                         if (NodeType != XmlNodeType.Element)
1256                                 throw new InvalidOperationException (String.Format ("'{0}' is an element node.", NodeType));
1257                         ReadStartElement (localName, namespaceURI);
1258                         if (isEmpty)
1259                                 return String.Empty;
1260                         string s = ReadContentString (false);
1261                         ReadEndElement ();
1262                         return s;
1263                 }
1264
1265                 public virtual bool ReadContentAsBoolean ()
1266                 {
1267                         try {
1268                                 return XQueryConvert.StringToBoolean (ReadContentString ());
1269                         } catch (FormatException ex) {
1270                                 throw XmlError ("Typed value is invalid.", ex);
1271                         }
1272                 }
1273
1274                 public virtual DateTime ReadContentAsDateTime ()
1275                 {
1276                         try {
1277                                 return XQueryConvert.StringToDateTime (ReadContentString ());
1278                         } catch (FormatException ex) {
1279                                 throw XmlError ("Typed value is invalid.", ex);
1280                         }
1281                 }
1282
1283                 public virtual decimal ReadContentAsDecimal ()
1284                 {
1285                         try {
1286                                 return XQueryConvert.StringToDecimal (ReadContentString ());
1287                         } catch (FormatException ex) {
1288                                 throw XmlError ("Typed value is invalid.", ex);
1289                         }
1290                 }
1291
1292                 public virtual double ReadContentAsDouble ()
1293                 {
1294                         try {
1295                                 return XQueryConvert.StringToDouble (ReadContentString ());
1296                         } catch (FormatException ex) {
1297                                 throw XmlError ("Typed value is invalid.", ex);
1298                         }
1299                 }
1300
1301                 public virtual float ReadContentAsFloat ()
1302                 {
1303                         try {
1304                                 return XQueryConvert.StringToFloat (ReadContentString ());
1305                         } catch (FormatException ex) {
1306                                 throw XmlError ("Typed value is invalid.", ex);
1307                         }
1308                 }
1309
1310                 public virtual int ReadContentAsInt ()
1311                 {
1312                         try {
1313                                 return XQueryConvert.StringToInt (ReadContentString ());
1314                         } catch (FormatException ex) {
1315                                 throw XmlError ("Typed value is invalid.", ex);
1316                         }
1317                 }
1318
1319                 public virtual long ReadContentAsLong ()
1320                 {
1321                         try {
1322                                 return XQueryConvert.StringToInteger (ReadContentString ());
1323                         } catch (FormatException ex) {
1324                                 throw XmlError ("Typed value is invalid.", ex);
1325                         }
1326                 }
1327
1328                 public virtual string ReadContentAsString ()
1329                 {
1330                         return ReadContentString ();
1331                 }
1332
1333                 public virtual int ReadContentAsBase64 (
1334                         byte [] buffer, int index, int count)
1335                 {
1336                         CheckSupport ();
1337                         return binary.ReadContentAsBase64 (
1338                                 buffer, index, count);
1339                 }
1340
1341                 public virtual int ReadContentAsBinHex (
1342                         byte [] buffer, int index, int count)
1343                 {
1344                         CheckSupport ();
1345                         return binary.ReadContentAsBinHex (
1346                                 buffer, index, count);
1347                 }
1348
1349                 public virtual int ReadElementContentAsBase64 (
1350                         byte [] buffer, int index, int count)
1351                 {
1352                         CheckSupport ();
1353                         return binary.ReadElementContentAsBase64 (
1354                                 buffer, index, count);
1355                 }
1356
1357                 public virtual int ReadElementContentAsBinHex (
1358                         byte [] buffer, int index, int count)
1359                 {
1360                         CheckSupport ();
1361                         return binary.ReadElementContentAsBinHex (
1362                                 buffer, index, count);
1363                 }
1364
1365                 private void CheckSupport ()
1366                 {
1367                         // Default implementation expects both.
1368                         if (!CanReadBinaryContent || !CanReadValueChunk)
1369                                 throw new NotSupportedException ();
1370                         if (binary == null)
1371                                 binary = new XmlReaderBinarySupport (this);
1372                 }
1373                 
1374 #endif
1375
1376                 public virtual int ReadValueChunk (char [] buffer, int index, int count)
1377                 {
1378                         if (!CanReadValueChunk)
1379                                 throw new NotSupportedException ();
1380                         if (binary == null)
1381                                 binary = new XmlReaderBinarySupport (this);
1382                         return binary.ReadValueChunk (buffer, index, count);
1383                 }
1384
1385                 public abstract void ResolveEntity ();
1386
1387                 public virtual void Skip ()
1388                 {
1389                         if (ReadState != ReadState.Interactive)
1390                                 return;
1391
1392                         MoveToElement ();
1393                         if (NodeType != XmlNodeType.Element || IsEmptyElement) {
1394                                 Read ();
1395                                 return;
1396                         }
1397                                 
1398                         int depth = Depth;
1399                         while (Read () && depth < Depth)
1400                                 ;
1401                         if (NodeType == XmlNodeType.EndElement)
1402                                 Read ();
1403                 }
1404
1405                 private XmlException XmlError (string message)
1406                 {
1407                         return new XmlException (this as IXmlLineInfo, BaseURI, message);
1408                 }
1409 #if NET_2_0
1410                 private XmlException XmlError (string message, Exception innerException)
1411                 {
1412                         return new XmlException (this as IXmlLineInfo, BaseURI, message);
1413                 }
1414 #endif
1415                 #endregion
1416
1417 #if NET_4_5
1418                 #region .NET 4.5 Async Methods
1419
1420                 bool asyncRunning;
1421
1422                 void StartAsync ()
1423                 {
1424                         if (!settings.Async)
1425                                 throw new InvalidOperationException ("Set XmlReaderSettings.Async to true if you want to use Async Methods.");
1426                         lock (this) {
1427                                 if (asyncRunning)
1428                                         throw new InvalidOperationException ("An asynchronous operation is already in progress.");
1429                                 asyncRunning = true;
1430                         }
1431                 }
1432
1433                 public virtual Task<bool> ReadAsync ()
1434                 {
1435                         StartAsync ();
1436                         return Task.Run (() => {
1437                                 try {
1438                                         return Read ();
1439                                 } finally {
1440                                         asyncRunning = false;
1441                                 }
1442                         });
1443                 }
1444
1445                 public virtual Task<string> GetValueAsync ()
1446                 {
1447                         StartAsync ();
1448                         return Task.Run (() => {
1449                                 try {
1450                                         return Value;
1451                                 } finally {
1452                                         asyncRunning = false;
1453                                 }
1454                         });
1455                 }
1456
1457                 public virtual Task<string> ReadInnerXmlAsync ()
1458                 {
1459                         StartAsync ();
1460                         return Task.Run (() => {
1461                                 try {
1462                                         return ReadInnerXml ();
1463                                 } finally {
1464                                         asyncRunning = false;
1465                                 }
1466                         });
1467                 }
1468
1469                 public virtual Task<string> ReadOuterXmlAsync ()
1470                 {
1471                         StartAsync ();
1472                         return Task.Run (() => {
1473                                 try {
1474                                         return ReadOuterXml ();
1475                                 } finally {
1476                                         asyncRunning = false;
1477                                 }
1478                         });
1479                 }
1480
1481                 public virtual Task<string> ReadContentAsStringAsync ()
1482                 {
1483                         StartAsync ();
1484                         return Task.Run (() => {
1485                                 try {
1486                                         return ReadContentAsString ();
1487                                 } finally {
1488                                         asyncRunning = false;
1489                                 }
1490                         });
1491                 }
1492
1493                 public virtual Task<int> ReadContentAsBase64Async (byte[] buffer, int index, int count)
1494                 {
1495                         StartAsync ();
1496                         return Task.Run (() => {
1497                                 try {
1498                                         return ReadContentAsBase64 (buffer, index, count);
1499                                 } finally {
1500                                         asyncRunning = false;
1501                                 }
1502                         });
1503                 }
1504
1505                 public virtual Task<int> ReadContentAsBinHexAsync (byte[] buffer, int index, int count)
1506                 {
1507                         StartAsync ();
1508                         return Task.Run (() => {
1509                                 try {
1510                                         return ReadContentAsBinHex (buffer, index, count);
1511                                 } finally {
1512                                         asyncRunning = false;
1513                                 }
1514                         });
1515                 }
1516
1517                 public virtual Task<int> ReadElementContentAsBase64Async (byte[] buffer, int index, int count)
1518                 {
1519                         StartAsync ();
1520                         return Task.Run (() => {
1521                                 try {
1522                                         return ReadElementContentAsBase64 (buffer, index, count);
1523                                 } finally {
1524                                         asyncRunning = false;
1525                                 }
1526                         });
1527                 }
1528
1529                 public virtual Task<int> ReadElementContentAsBinHexAsync (byte[] buffer, int index, int count)
1530                 {
1531                         StartAsync ();
1532                         return Task.Run (() => {
1533                                 try {
1534                                         return ReadElementContentAsBinHex (buffer, index, count);
1535                                 } finally {
1536                                         asyncRunning = false;
1537                                 }
1538                         });
1539                 }
1540
1541                 public virtual Task<int> ReadValueChunkAsync (char[] buffer, int index, int count)
1542                 {
1543                         StartAsync ();
1544                         return Task.Run (() => {
1545                                 try {
1546                                         return ReadValueChunk (buffer, index, count);
1547                                 } finally {
1548                                         asyncRunning = false;
1549                                 }
1550                         });
1551                 }
1552
1553                 public virtual Task<object> ReadContentAsAsync (Type returnType, IXmlNamespaceResolver namespaceResolver)
1554                 {
1555                         StartAsync ();
1556                         return Task.Run (() => {
1557                                 try {
1558                                         return ReadContentAs (returnType, namespaceResolver);
1559                                 } finally {
1560                                         asyncRunning = false;
1561                                 }
1562                         });
1563                 }
1564
1565                 public virtual Task<object> ReadContentAsObjectAsync ()
1566                 {
1567                         StartAsync ();
1568                         return Task.Run (() => {
1569                                 try {
1570                                         return ReadContentAsObject ();
1571                                 } finally {
1572                                         asyncRunning = false;
1573                                 }
1574                         });
1575                 }
1576
1577                 public virtual Task<object> ReadElementContentAsAsync (Type returnType, IXmlNamespaceResolver namespaceResolver)
1578                 {
1579                         StartAsync ();
1580                         return Task.Run (() => {
1581                                 try {
1582                                         return ReadElementContentAs (returnType, namespaceResolver);
1583                                 } finally {
1584                                         asyncRunning = false;
1585                                 }
1586                         });
1587                 }
1588
1589                 public virtual Task<object> ReadElementContentAsObjectAsync ()
1590                 {
1591                         StartAsync ();
1592                         return Task.Run (() => {
1593                                 try {
1594                                         return ReadElementContentAsObject ();
1595                                 } finally {
1596                                         asyncRunning = false;
1597                                 }
1598                         });
1599                 }
1600
1601                 public virtual Task<string> ReadElementContentAsStringAsync ()
1602                 {
1603                         StartAsync ();
1604                         return Task.Run (() => {
1605                                 try {
1606                                         return ReadElementContentAsString ();
1607                                 } finally {
1608                                         asyncRunning = false;
1609                                 }
1610                         });
1611                 }
1612
1613                 public virtual Task<XmlNodeType> MoveToContentAsync ()
1614                 {
1615                         StartAsync ();
1616                         return Task.Run (() => {
1617                                 try {
1618                                         return MoveToContent ();
1619                                 } finally {
1620                                         asyncRunning = false;
1621                                 }
1622                         });
1623                 }
1624
1625                 public virtual Task SkipAsync ()
1626                 {
1627                         StartAsync ();
1628                         return Task.Run (() => {
1629                                 try {
1630                                         Skip ();
1631                                 } finally {
1632                                         asyncRunning = false;
1633                                 }
1634                         });
1635                 }
1636
1637                 #endregion
1638 #endif
1639         }
1640 }