Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / System.XML / System.Xml / XmlTextReader.cs
index de927664636eb46185eb00a6ad6bc9c418dea1f6..d50d8954cbd8749253421634e78c68666186b2fd 100644 (file)
 
 using System;
 using System.Collections;
-#if NET_2_0
 using System.Collections.Generic;
-#endif
 using System.Globalization;
 using System.IO;
 using System.Security.Permissions;
 using System.Text;
 using System.Xml.Schema;
 using Mono.Xml;
-
-#if NET_2_0
 using System.Xml;
 
 namespace Mono.Xml2
-#else
-namespace System.Xml
-#endif
 {
-
-#if NET_2_0
-       internal class XmlTextReader : XmlReader,
+       class XmlTextReader : XmlReader,
                IXmlLineInfo, IXmlNamespaceResolver, IHasXmlParserContext
-#else
-       [PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)]
-       public class XmlTextReader : XmlReader, IXmlLineInfo, IHasXmlParserContext
-#endif
        {
                #region Constructors
 
@@ -111,13 +98,13 @@ namespace System.Xml
 
                public XmlTextReader (string url, XmlNameTable nt)
                {
-                       string uriString;
-                       Stream stream = GetStreamFromUrl (url, out uriString);
+                       reader_uri = resolver.ResolveUri (null, url);
+                       string uriString = (reader_uri == null) ? String.Empty : reader_uri.ToString ();
                        XmlParserContext ctx = new XmlParserContext (nt,
                                new XmlNamespaceManager (nt),
                                String.Empty,
                                XmlSpace.None);
-                       this.InitializeContext (uriString, ctx, new XmlStreamReader (stream), XmlNodeType.Document);
+                       this.InitializeContext (uriString, ctx, null, XmlNodeType.Document);
                }
 
                public XmlTextReader (TextReader input, XmlNameTable nt)
@@ -130,7 +117,7 @@ namespace System.Xml
                internal XmlTextReader (bool dummy, XmlResolver resolver, string url, XmlNodeType fragType, XmlParserContext context)
                {
                        if (resolver == null) {
-#if NET_2_1
+#if MOONLIGHT
                                resolver = new XmlXapResolver ();
 #else
                                resolver = new XmlUrlResolver ();
@@ -138,6 +125,7 @@ namespace System.Xml
                        }
                        this.XmlResolver = resolver;
                        string uriString;
+
                        Stream stream = GetStreamFromUrl (url, out uriString);
                        this.InitializeContext (uriString, context, new XmlStreamReader (stream), fragType);
                }
@@ -180,9 +168,20 @@ namespace System.Xml
                        InitializeContext (url, context, fragment, fragType);
                }
 
-               private Stream GetStreamFromUrl (string url, out string absoluteUriString)
+               Uri ResolveUri (string url)
+               {
+                       return resolver.ResolveUri (null, url);
+               }
+
+               Stream GetStreamFromUrl (string url, out string absoluteUriString)
                {
-                       Uri uri = resolver.ResolveUri (null, url);
+#if NET_2_1
+                       if (url == null)
+                               throw new ArgumentNullException ("url");
+                       if (url.Length == 0)
+                               throw new ArgumentException ("url");
+#endif
+                       Uri uri = ResolveUri (url);
                        absoluteUriString = uri != null ? uri.ToString () : String.Empty;
                        return resolver.GetEntity (uri, null, typeof (Stream)) as Stream;
                }
@@ -201,7 +200,6 @@ namespace System.Xml
                        get { return parserContext.BaseURI; }
                }
 
-#if NET_2_0
                public override bool CanReadBinaryContent {
                        get { return true; }
                }
@@ -209,15 +207,6 @@ namespace System.Xml
                public override bool CanReadValueChunk {
                        get { return true; }
                }
-#else
-               internal override bool CanReadBinaryContent {
-                       get { return true; }
-               }
-
-               internal override bool CanReadValueChunk {
-                       get { return true; }
-               }
-#endif
 
                internal bool CharacterChecking {
                        get { return checkCharacters; }
@@ -246,12 +235,11 @@ namespace System.Xml
                {
                        get { return parserContext.Encoding; }
                }
-#if NET_2_0
+
                public EntityHandling EntityHandling {
                        get { return entityHandling; }
                        set { entityHandling = value; }
                }
-#endif
 
                public override bool EOF {
                        get { return readState == ReadState.EndOfFile; }
@@ -270,21 +258,6 @@ namespace System.Xml
                        get { return cursorToken.IsEmptyElement; }
                }
 
-#if NET_2_0
-#else
-               public override string this [int i] {
-                       get { return GetAttribute (i); }
-               }
-
-               public override string this [string name] {
-                       get { return GetAttribute (name); }
-               }
-
-               public override string this [string localName, string namespaceName] {
-                       get { return GetAttribute (localName, namespaceName); }
-               }
-#endif
-
                public int LineNumber {
                        get {
                                if (useProceedingLineInfo)
@@ -354,11 +327,9 @@ namespace System.Xml
                        get { return readState; }
                }
 
-#if NET_2_0
                public override XmlReaderSettings Settings {
                        get { return base.Settings; }
                }
-#endif
 
                public override string Value {
                        get { return cursorToken.Value != null ? cursorToken.Value : String.Empty; }
@@ -418,6 +389,7 @@ namespace System.Xml
 
                private int GetIndexOfQualifiedAttribute (string localName, string namespaceURI)
                {
+                       namespaceURI = namespaceURI ?? String.Empty;
                        for (int i = 0; i < attributeCount; i++) {
                                XmlAttributeTokenInfo ti = attributeTokens [i];
                                if (ti.LocalName == localName && ti.NamespaceURI == namespaceURI)
@@ -438,7 +410,6 @@ namespace System.Xml
                        return attributeTokens [idx].Value;
                }
 
-#if NET_2_0
                public IDictionary<string, string> GetNamespacesInScope (XmlNamespaceScope scope)
                {
                        return nsmgr.GetNamespacesInScope (scope);
@@ -448,7 +419,6 @@ namespace System.Xml
                {
                        return GetNamespacesInScope (scope);
                }
-#endif
 
                public TextReader GetRemainder ()
                {
@@ -457,11 +427,7 @@ namespace System.Xml
                        return new StringReader (new string (peekChars, peekCharsIndex, peekCharsLength - peekCharsIndex) + reader.ReadToEnd ());
                }
 
-#if NET_2_0
                public bool HasLineInfo ()
-#else
-               bool IXmlLineInfo.HasLineInfo ()
-#endif
                {
                        return true;
                }
@@ -478,7 +444,6 @@ namespace System.Xml
                        return s == String.Empty ? null : s;
                }
 
-#if NET_2_0
                string IXmlNamespaceResolver.LookupPrefix (string ns)
                {
                        return LookupPrefix (ns, false);
@@ -488,7 +453,6 @@ namespace System.Xml
                {
                        return nsmgr.LookupPrefix (ns, atomizedName);
                }
-#endif
 
                public override void MoveToAttribute (int i)
                {
@@ -707,13 +671,11 @@ namespace System.Xml
                        throw new InvalidOperationException ("XmlTextReader cannot resolve external entities.");
                }
 
-#if NET_2_0
                [MonoTODO] // FIXME: Implement, for performance improvement
                public override void Skip ()
                {
                        base.Skip ();
                }
-#endif
                #endregion
 
                #region Internals
@@ -921,6 +883,7 @@ namespace System.Xml
 
                private StringBuilder valueBuffer;
 
+               Uri reader_uri;
                private TextReader reader;
                private char [] peekChars;
                private int peekCharsIndex;
@@ -952,7 +915,7 @@ namespace System.Xml
                // These values are never re-initialized.
                private bool namespaces = true;
                private WhitespaceHandling whitespaceHandling = WhitespaceHandling.All;
-#if NET_2_1
+#if MOONLIGHT
                private XmlResolver resolver = new XmlXapResolver ();
 #else
                private XmlResolver resolver = new XmlUrlResolver ();
@@ -983,10 +946,8 @@ namespace System.Xml
 #endif
 
                        checkCharacters = true;
-#if NET_2_0
                        if (Settings != null)
                                checkCharacters = Settings.CheckCharacters;
-#endif
                        prohibitDtd = false;
                        closeInput = true;
                        entityHandling = EntityHandling.ExpandCharEntities;
@@ -1054,6 +1015,9 @@ namespace System.Xml
                        nsmgr = nsmgr != null ? nsmgr : new XmlNamespaceManager (nameTable);
 
                        if (url != null && url.Length > 0) {
+#if NET_2_1
+                               Uri uri = new Uri (url, UriKind.RelativeOrAbsolute);
+#else
                                Uri uri = null;
                                try {
                                        uri = new Uri (url, UriKind.RelativeOrAbsolute);
@@ -1061,6 +1025,7 @@ namespace System.Xml
                                        string path = Path.GetFullPath ("./a");
                                        uri = new Uri (new Uri (path), url);
                                }
+#endif
                                parserContext.BaseURI = uri.ToString ();
                        }
 
@@ -1083,7 +1048,6 @@ namespace System.Xml
                        }
                }
 
-#if NET_2_0
                internal ConformanceLevel Conformance {
                        get { return allowMultipleRoot ? ConformanceLevel.Fragment : ConformanceLevel.Document; }
                        set {
@@ -1104,7 +1068,6 @@ namespace System.Xml
                {
                        parserContext.NameTable = nameTable;
                }
-#endif
 
                // Use this method rather than setting the properties
                // directly so that all the necessary properties can
@@ -1224,6 +1187,12 @@ namespace System.Xml
 
                private bool ReadTextReader (int remained)
                {
+                       if (reader == null && reader_uri != null) {
+                               Uri uri = reader_uri;
+                               reader_uri = null;
+                               string uriString;
+                               reader = new XmlStreamReader (GetStreamFromUrl (uri.ToString (), out uriString));
+                       }
                        if (peekCharsLength < 0) {      // initialized buffer
                                peekCharsLength = reader.Read (peekChars, 0, peekChars.Length);
                                return peekCharsLength > 0;
@@ -1459,6 +1428,10 @@ namespace System.Xml
                                                Uri buri =
                                                        BaseURI != String.Empty ?
                                                        new Uri (BaseURI) : null;
+                                               // xml:base="" without any base URI -> pointless. However there are
+                                               // some people who use such xml:base. Seealso bug #608391.
+                                               if (buri == null && String.IsNullOrEmpty (value))
+                                                       break;
                                                Uri uri = resolver.ResolveUri (
                                                        buri, value);
                                                parserContext.BaseURI =
@@ -1566,7 +1539,7 @@ namespace System.Xml
 
                private void AppendValueChar (int ch)
                {
-                       if (ch < Char.MaxValue)
+                       if (ch <= Char.MaxValue)
                                valueBuffer.Append ((char) ch);
                        else
                                AppendSurrogatePairValueChar (ch);
@@ -1593,7 +1566,7 @@ namespace System.Xml
                                        break;
                                if (whitespacePool == null)
                                        whitespacePool = new NameTable ();
-#if NET_2_0 && !NET_2_1
+#if !NET_2_1
                                valueBuffer.CopyTo (0, whitespaceCache, 0, len);
 #else
                                for (int i = 0; i < len; i++)
@@ -1648,7 +1621,7 @@ namespace System.Xml
                                // FIXME: it might be optimized by the JIT later,
 //                             AppendValueChar (ch);
                                {
-                                       if (ch < Char.MaxValue)
+                                       if (ch <= Char.MaxValue)
                                                valueBuffer.Append ((char) ch);
                                        else
                                                AppendSurrogatePairValueChar (ch);
@@ -1819,7 +1792,7 @@ namespace System.Xml
                {
                        IncrementAttributeToken ();
                        XmlAttributeTokenInfo ati = attributeTokens [currentAttribute];
-                       ati.Name = parserContext.NameTable.Add (name);
+                       ati.Name = NameTable.Add (name);
                        ati.Prefix = String.Empty;
                        ati.NamespaceURI = String.Empty;
                        IncrementAttributeValueToken ();
@@ -1942,14 +1915,11 @@ namespace System.Xml
                                        int predefined = XmlChar.GetPredefinedEntity (entName);
                                        if (predefined < 0) {
                                                CheckAttributeEntityReferenceWFC (entName);
-#if NET_2_0
                                                if (entityHandling == EntityHandling.ExpandEntities) {
                                                        string value = DTD.GenerateEntityAttributeText (entName);
                                                        foreach (char c in (IEnumerable<char>) value)
                                                                AppendValueChar (c);
-                                               } else
-#endif
-                                               {
+                                               } else {
                                                        currentAttributeValueToken.ValueBufferEnd = valueBuffer.Length;
                                                        currentAttributeValueToken.NodeType = XmlNodeType.Text;
                                                        if (!isNewToken)
@@ -1969,7 +1939,7 @@ namespace System.Xml
                                        // FIXME: it might be optimized by the JIT later,
 //                                     AppendValueChar (ch);
                                        {
-                                               if (ch < Char.MaxValue)
+                                               if (ch <= Char.MaxValue)
                                                        valueBuffer.Append ((char) ch);
                                                else
                                                        AppendSurrogatePairValueChar (ch);
@@ -2240,13 +2210,11 @@ namespace System.Xml
                                }
                                // Encoding value should be checked inside XmlInputStream.
                        }
-#if NET_2_0
                        // this condition is to check if this instance is
                        // not created by XmlReader.Create() (which just
                        // omits strict text declaration check).
                        else if (Conformance == ConformanceLevel.Auto)
                                throw NotWFError ("Encoding declaration is mandatory in text declaration.");
-#endif
 
                        Expect ("?>");
 
@@ -2362,7 +2330,7 @@ namespace System.Xml
                                // FIXME: it might be optimized by the JIT later,
 //                             AppendValueChar (ch);
                                {
-                                       if (ch < Char.MaxValue)
+                                       if (ch <= Char.MaxValue)
                                                valueBuffer.Append ((char) ch);
                                        else
                                                AppendSurrogatePairValueChar (ch);
@@ -2760,7 +2728,7 @@ namespace System.Xml
                        // AppendNameChar (ch);
                        {
                                // nameBuffer.Length is always non-0 so no need to ExpandNameCapacity () here
-                               if (ch < Char.MaxValue)
+                               if (ch <= Char.MaxValue)
                                        nameBuffer [nameLength++] = (char) ch;
                                else
                                        AppendSurrogatePairNameChar (ch);
@@ -2777,7 +2745,7 @@ namespace System.Xml
                                {
                                        if (nameLength == nameCapacity)
                                                ExpandNameCapacity ();
-                                       if (ch < Char.MaxValue)
+                                       if (ch <= Char.MaxValue)
                                                nameBuffer [nameLength++] = (char) ch;
                                        else
                                                AppendSurrogatePairNameChar (ch);
@@ -2906,11 +2874,6 @@ namespace System.Xml
                                case -1:
                                        throw NotWFError ("Unexpected end of xml.");
                                case '<':
-                                       if (i + 1 == length)
-                                               // if it does not end here,
-                                               // it cannot store another
-                                               // character, so stop here.
-                                               return i;
                                        Advance (c);
                                        if (PeekChar () != '/') {
                                                nestLevel++;
@@ -2933,7 +2896,7 @@ namespace System.Xml
                                        return i;
                                default:
                                        Advance (c);
-                                       if (c < Char.MaxValue)
+                                       if (c <= Char.MaxValue)
                                                buffer [bufIndex++] = (char) c;
                                        else {
                                                buffer [bufIndex++] = (char) ((c - 0x10000) / 0x400 + 0xD800);