Forráskód Böngészése

2003-08-18 Ben Maurer <[email protected]>

        * System.Xml.dll.source: add System.Xml/HighWaterStack.cs
        * XmlChar.cs (IsWhitespace): Spare enumerator allocation.
        * XmlTextWriter.cs (WriteWhitespace): Enumerators are very high in
        fat, use low-fat loops instead. Even better, call the function
        inside XmlChar for code reuse.
        * HighWaterStack.cs (added): New class that acts like a Stack, but
        helps with memory allocation.
        * XmlNamespaceManager.cs, XmlParserContext.cs: Rewrote to use
        HighWaterStack.
        * XmlTextReader.cs: Remove orderedAttributesEnumerator variable,
        use a variable that stores the position in the ArrayList.

svn path=/trunk/mcs/; revision=17385
Ben Maurer 22 éve
szülő
commit
e3dbc393a2

+ 4 - 0
mcs/class/System.XML/ChangeLog

@@ -1,3 +1,7 @@
+2003-08-18 Ben Maurer  <[email protected]>
+
+	* System.Xml.dll.source: add System.Xml/HighWaterStack.cs.
+
 2003-08-14  Atsushi Enomoto <[email protected]>
 
 	* System.Xml.dll.sources: Added Mono.Xml.Xsl.Operation/XslComment.cs 

+ 1 - 0
mcs/class/System.XML/System.Xml.dll.sources

@@ -45,6 +45,7 @@ System.Xml/DTDObjectModel.cs
 System.Xml/DTDValidatingReader.cs
 System.Xml/EntityHandling.cs
 System.Xml/Formatting.cs
+System.Xml/HighWaterStack.cs
 System.Xml/IXmlLineInfo.cs
 System.Xml/NameTable.cs
 System.Xml/ReadState.cs

+ 13 - 0
mcs/class/System.XML/System.Xml/ChangeLog

@@ -1,3 +1,16 @@
+2003-08-18 Ben Maurer  <[email protected]>
+
+	* XmlChar.cs (IsWhitespace): Spare enumerator allocation.
+	* XmlTextWriter.cs (WriteWhitespace): Enumerators are very high in
+	fat, use low-fat loops instead. Even better, call the function
+	inside XmlChar for code reuse.
+	* HighWaterStack.cs (added): New class that acts like a Stack, but
+	helps with memory allocation.
+	* XmlNamespaceManager.cs, XmlParserContext.cs: Rewrote to use
+	HighWaterStack.
+	* XmlTextReader.cs: Remove orderedAttributesEnumerator variable,
+	use a variable that stores the position in the ArrayList.
+	
 2003-08-18 Ben Maurer  <[email protected]>
 
 	* XmlTextWriter.cs: Begin diet. String.Format has too much

+ 3 - 3
mcs/class/System.XML/System.Xml/XmlChar.cs

@@ -19,9 +19,9 @@ namespace System.Xml
 
 		internal static bool IsWhitespace (string str)
 		{
-			foreach (char c in str)
-				if (!IsWhitespace (c))
-					return false;
+			for (int i = 0; i < str.Length; i++)
+				if (!IsWhitespace (str [i])) return false;
+				
 			return true;
 		}
 

+ 118 - 64
mcs/class/System.XML/System.Xml/XmlNamespaceManager.cs

@@ -16,10 +16,16 @@ namespace System.Xml
 		#region Fields
 
 		private XmlNameTable nameTable;
-		private NamespaceScope currentScope;
+			
+		HighWaterStack decls = new HighWaterStack (50);
+		HighWaterStack scopes = new HighWaterStack (50);
+		Namespace defaultNamespace;
+		int count = 0;
+		
 		internal const string XmlnsXml = "http://www.w3.org/XML/1998/namespace";
 		internal const string XmlnsXmlns = "http://www.w3.org/2000/xmlns/";
 
+		string XMLNS, XML, XMLNS_URL, XML_URL;
 		#endregion
 
 		#region Constructor
@@ -28,16 +34,10 @@ namespace System.Xml
 		{
 			this.nameTable = nameTable;
 
-			nameTable.Add ("xmlns");
-			nameTable.Add ("xml");
-			nameTable.Add (String.Empty);
-			nameTable.Add (XmlnsXmlns);
-			nameTable.Add (XmlnsXml);
-
-			PushScope ();
-			currentScope.Namespaces = new Hashtable ();
-			currentScope.Namespaces.Add ("xml", XmlnsXml);
-			currentScope.Namespaces.Add ("xmlns", XmlnsXmlns);
+			XMLNS = nameTable.Add ("xmlns");
+			XML = nameTable.Add ("xml");
+			XMLNS_URL = nameTable.Add (XmlnsXmlns);
+			XML_URL = nameTable.Add (XmlnsXml);
 		}
 
 		#endregion
@@ -45,7 +45,7 @@ namespace System.Xml
 		#region Properties
 
 		public virtual string DefaultNamespace {
-			get { return LookupNamespace (String.Empty); }
+			get { return (defaultNamespace == null) ? String.Empty : defaultNamespace.Uri; }
 		}
 
 		public XmlNameTable NameTable {
@@ -66,12 +66,30 @@ namespace System.Xml
 
 			IsValidDeclaration (prefix, uri, true);
 
-			if (currentScope.Namespaces == null)
-				currentScope.Namespaces = new Hashtable ();
+			prefix = nameTable.Add (prefix);
+			uri = nameTable.Add (uri);
 
-			if (prefix != String.Empty)
-				nameTable.Add (prefix);
-			currentScope.Namespaces [prefix] = nameTable.Add (uri);
+			// Is it already in the table?
+			for (int i = decls.Length - 1; i >= decls.Length - count; i--) {
+				Namespace decl = (Namespace)decls [i];
+				if (AtomStrEq (decl.Prefix, prefix)) {
+					// Then redefine it
+					decl.Uri = uri;
+					return;
+				}
+			}
+			
+			// Otherwise, we are going to add it as a new object
+			Namespace newDecl = (Namespace) decls.Push ();
+			if (newDecl == null) {
+				newDecl = new Namespace ();
+				decls.AddToTop (newDecl);
+			}
+			newDecl.Prefix = prefix;
+			newDecl.Uri = uri;
+			count++;
+			if (prefix == String.Empty)
+				defaultNamespace = newDecl;
 		}
 
 		internal static string IsValidDeclaration (string prefix, string uri, bool throwException)
@@ -93,56 +111,72 @@ namespace System.Xml
 
 		public virtual IEnumerator GetEnumerator ()
 		{
-			if (currentScope.Namespaces == null)
-				currentScope.Namespaces = new Hashtable ();
-
-			return currentScope.Namespaces.Keys.GetEnumerator ();
+			Hashtable p = new Hashtable (count);
+			for (int i = decls.Length - 1; i >= decls.Length - count; i--) {
+				Namespace decl = (Namespace)decls [i];
+				if (decl.Prefix != String.Empty && decl.Uri != null)
+					p [decl.Prefix] = decl.Uri;
+			}
+			p [String.Empty] = DefaultNamespace;
+			p [XML] = XML_URL;
+			p [XMLNS] = XMLNS_URL;
+			return p.Keys.GetEnumerator ();
 		}
 
 		public virtual bool HasNamespace (string prefix)
 		{
-			return currentScope != null && currentScope.Namespaces != null && currentScope.Namespaces.Contains (prefix);
+			if (prefix == null) return false;
+			
+			for (int i = decls.Length - 1; i >= decls.Length - count; i--) {
+				Namespace decl = (Namespace)decls [i];
+				if (AtomStrEq (decl.Prefix, prefix) && decl.Uri != null)
+					return true;
+			}
+			return false;
 		}
 
 		public virtual string LookupNamespace (string prefix)
 		{
-			NamespaceScope scope = currentScope;
+			if (prefix == null)
+				return null;
 
-			while (scope != null) {
-				if (scope.Namespaces != null && scope.Namespaces.Contains (prefix))
-					return scope.Namespaces[prefix] as string;
-				scope = scope.Next;
-			}
+			if (prefix == String.Empty)
+				return DefaultNamespace;
 
-			switch (prefix) {
-			case "xmlns":
-				return nameTable.Get (XmlnsXmlns);
-			case "xml":
-				return nameTable.Get (XmlnsXml);
-			case "":
-				return nameTable.Get (String.Empty);
-			}
+			if (AtomStrEq (XML, prefix))
+				return XML_URL;
+
+			if (AtomStrEq (XMLNS, prefix))
+				return XMLNS_URL;
 
+			for (int i = decls.Length - 1; i >= 0; i--) {
+				Namespace decl = (Namespace)decls [i];
+				if (AtomStrEq (decl.Prefix, prefix) && decl.Uri != null)
+					return decl.Uri;
+			}
 			return null;
 		}
 
+
 		public virtual string LookupPrefix (string uri)
 		{
 			if (uri == null)
 				return null;
 
-			NamespaceScope scope = currentScope;
+			if (AtomStrEq (DefaultNamespace, uri))
+				return String.Empty;
+			
+			if (AtomStrEq (XML_URL, uri))
+				return XML;
+			
+			if (AtomStrEq (XMLNS_URL, uri))
+				return XMLNS;
 
-			while (scope != null) 
-			{
-				if (scope.Namespaces != null && scope.Namespaces.ContainsValue (uri)) {
-					foreach (DictionaryEntry entry in scope.Namespaces) {
-						if (entry.Value.ToString() == uri)
-							return nameTable.Get (entry.Key as string) as string;
-					}
-				}
 
-				scope = scope.Next;
+			for (int i = decls.Length - 1; i >= 0; i--) {
+				Namespace decl = (Namespace)decls [i];
+				if (AtomStrEq (decl.Uri, uri) && decl.Uri != null)
+					return decl.Prefix;
 			}
 
 			// ECMA specifies that this method returns String.Empty
@@ -155,17 +189,29 @@ namespace System.Xml
 
 		public virtual bool PopScope ()
 		{
-			if (currentScope != null)
-				currentScope = currentScope.Next;
-
-			return currentScope != null;
+			Scope current = (Scope)scopes.Pop ();
+			if (current == null) {
+				return false;
+			} else {
+				for (int i = 0; i < count; i++)
+					decls.Pop ();
+					
+				defaultNamespace = current.DefaultNamespace;
+				count = current.Count;
+				return true;
+			}
 		}
 
 		public virtual void PushScope ()
 		{
-			NamespaceScope newScope = new NamespaceScope ();
-			newScope.Next = currentScope;
-			currentScope = newScope;
+			Scope current = (Scope)scopes.Push ();
+			if (current == null) {
+				current = new Scope ();
+				scopes.AddToTop (current);
+			}
+			current.DefaultNamespace = defaultNamespace;
+			current.Count = count;
+			count = 0;
 		}
 
 		public virtual void RemoveNamespace (string prefix, string uri)
@@ -176,27 +222,35 @@ namespace System.Xml
 			if (uri == null)
 				throw new ArgumentNullException ("uri");
 
-			if (currentScope == null || currentScope.Namespaces == null)
-				return;
-
 			string p = nameTable.Get (prefix);
 			string u = nameTable.Get (uri);
 			if (p == null || u == null)
 				return;
 				
-			string storedUri = currentScope.Namespaces [p] as string;
-			if (storedUri == null || storedUri != u)
-				return;
+			for (int i = decls.Length - 1; i >= decls.Length - count; i--) {
+				Namespace n = (Namespace)decls [i];
+				if (AtomStrEq (n.Prefix, p) && AtomStrEq (n.Uri, u))
+					n.Uri = null;
+			}
+		}
+		
+		bool AtomStrEq (string a, string b) {
+			if (String.Equals (a, b) && !Object.ReferenceEquals (a, b)) {
+				Console.Error.WriteLine ("WARNING: {0} not interned", a);
+			}
+			
+			return String.Equals (a, b);
 
-			currentScope.Namespaces.Remove (p);
 		}
 
 		#endregion
+		class Namespace {
+			public string Prefix, Uri;
 	}
 
-	internal class NamespaceScope
-	{
-		internal NamespaceScope Next;
-		internal Hashtable Namespaces;
+		class Scope {
+			public Namespace DefaultNamespace;
+			public int Count;
+		}
 	}
 }

+ 29 - 31
mcs/class/System.XML/System.Xml/XmlParserContext.cs

@@ -134,18 +134,14 @@ namespace System.Xml
 			}
 			this.encoding = enc;
 
-			baseURIStack = new Stack ();
-			xmlLangStack = new Stack ();
-			xmlSpaceStack = new Stack ();
-			baseURIStack.Push (baseURI != null ? baseURI : String.Empty);
-			xmlLangStack.Push (xmlLang);
-			xmlSpaceStack.Push (xmlSpace);
+			PushScope ();
+			this.BaseURI = baseURI != null ? baseURI : String.Empty;
+			this.XmlLang = xmlLang;
+			this.XmlSpace = xmlSpace;
 		}
 		#endregion
 
 		#region Fields
-
-		private string baseURI;
 		private string docTypeName;
 		private Encoding encoding;
 		private string internalSubset;
@@ -153,11 +149,8 @@ namespace System.Xml
 		private XmlNameTable nameTable;
 		private string publicID;
 		private string systemID;
-		private string xmlLang;
-		private XmlSpace xmlSpace;
-		private Stack baseURIStack;
-		private Stack xmlLangStack;
-		private Stack xmlSpaceStack;
+		private HighWaterStack scopeStack = new HighWaterStack (50);
+		Scope current;
 		private DTDObjectModel dtd;
 
 		#endregion
@@ -165,8 +158,8 @@ namespace System.Xml
 		#region Properties
 
 		public string BaseURI {
-			get { return baseURI != null ? baseURI : baseURIStack.Peek () as string; }
-			set { baseURI = value; }
+			get { return current.baseUri; }
+			set { current.baseUri = value; }
 		}
 
 		public string DocTypeName {
@@ -210,13 +203,13 @@ namespace System.Xml
 		}
 
 		public string XmlLang {
-			get { return xmlLang != null ? xmlLang : xmlLangStack.Peek () as string; }
-			set { xmlLang = value; }
+			get { return current.xmlLang; }
+			set { current.xmlLang = value; }
 		}
 
 		public XmlSpace XmlSpace {
-			get { return xmlSpace != XmlSpace.None ? xmlSpace : (XmlSpace) xmlSpaceStack.Peek (); }
-			set { xmlSpace = value; }
+			get { return current.xmlSpace; }
+			set { current.xmlSpace = value; }
 		}
 
 		#endregion
@@ -224,22 +217,27 @@ namespace System.Xml
 		#region Methods
 		internal void PushScope ()
 		{
-			baseURIStack.Push (BaseURI);
-			xmlLangStack.Push (XmlLang);
-			xmlSpaceStack.Push (XmlSpace);
-			baseURI = null;
-			xmlLang = null;
-			xmlSpace = XmlSpace.None;
+			current = (Scope)scopeStack.Push ();
+			if (current == null) {
+				current = new Scope ();
+				scopeStack.AddToTop (current);
+			} else {
+				current.baseUri = String.Empty;
+				current.xmlLang = String.Empty;
+				current.xmlSpace = XmlSpace.None;
+			}
 		}
 
 		internal void PopScope ()
 		{
-			baseURIStack.Pop ();
-			xmlLangStack.Pop ();
-			xmlSpaceStack.Pop ();
-			baseURI = null;
-			xmlLang = null;
-			xmlSpace = XmlSpace.None;
+			current = (Scope)scopeStack.Pop ();
+		}
+		
+		class Scope {
+			public string baseUri, xmlLang;
+			public XmlSpace xmlSpace;
+			
+			public Scope () {}
 		}
 		#endregion
 	}

+ 14 - 19
mcs/class/System.XML/System.Xml/XmlTextReader.cs

@@ -390,13 +390,11 @@ namespace System.Xml
 			if (attributes == null || orderedAttributes.Count < i || i < 0)
 				throw new ArgumentOutOfRangeException ("attribute index out of range.");
 
-			if (orderedAttributesEnumerator == null) {
+			if (orderedAttributesPos == -1) {
 				SaveProperties ();
 			}
 
-			orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
-			for (int n=0; n<=i; n++)
-				orderedAttributesEnumerator.MoveNext();
+			orderedAttributesPos = i;
 
 			string name = orderedAttributes [i] as string;
 			string value = attributes [name] as string;
@@ -419,17 +417,15 @@ namespace System.Xml
 			if (attributes == null)
 				return false;
 
-			if (orderedAttributesEnumerator == null) {
+			if (orderedAttributesPos == -1) {
 				SaveProperties ();
 			}
 
-			orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
-			while (orderedAttributesEnumerator.MoveNext ()) {
-				if(name == orderedAttributesEnumerator.Current as string) {
+			for (orderedAttributesPos = 0; orderedAttributesPos < orderedAttributes.Count; orderedAttributesPos++)
+				if (name == orderedAttributes [orderedAttributesPos] as string) {
 					match = true;
 					break;
 				}
-			}
 
 			if (match) {
 				string value = attributes [name] as string;
@@ -463,8 +459,8 @@ namespace System.Xml
 
 		public override bool MoveToElement ()
 		{
-			if (orderedAttributesEnumerator != null) {
-				orderedAttributesEnumerator = null;
+			if (orderedAttributesPos != -1) {
+				orderedAttributesPos = -1;
 				if (isPropertySaved)
 					RestoreProperties ();
 				insideAttribute = false;
@@ -485,13 +481,12 @@ namespace System.Xml
 			if (attributes == null)
 				return false;
 
-			if (orderedAttributesEnumerator == null) {
+			if (orderedAttributesPos == -1)
 				SaveProperties ();
-				orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
-			}
 
-			if (orderedAttributesEnumerator.MoveNext ()) {
-				string name = orderedAttributesEnumerator.Current as string;
+
+			if (++orderedAttributesPos < orderedAttributes.Count) {
+				string name = orderedAttributes [orderedAttributesPos] as string;
 				string value = attributes [name] as string;
 				SetProperties (
 					XmlNodeType.Attribute, // nodeType
@@ -781,7 +776,7 @@ namespace System.Xml
 
 		private Hashtable attributes;
 		private ArrayList orderedAttributes;
-		private IEnumerator orderedAttributesEnumerator;
+		private int orderedAttributesPos = -1;
 
 		private bool returnEntityReference;
 		private string entityReferenceName;
@@ -849,7 +844,7 @@ namespace System.Xml
 			attributes = new Hashtable ();
 			attributeString = String.Empty;
 			orderedAttributes = new ArrayList ();
-			orderedAttributesEnumerator = null;
+			orderedAttributesPos = -1;
 
 			returnEntityReference = false;
 			entityReferenceName = String.Empty;
@@ -1012,7 +1007,7 @@ namespace System.Xml
 				orderedAttributes.Clear ();
 			}
 
-			orderedAttributesEnumerator = null;
+			orderedAttributesPos = -1;
 		}
 
 		private int PeekChar ()

+ 2 - 4
mcs/class/System.XML/System.Xml/XmlTextWriter.cs

@@ -821,10 +821,8 @@ namespace System.Xml
 
 		public override void WriteWhitespace (string ws)
 		{
-			foreach (char c in ws) {
-				if ((c != ' ') && (c != '\t') && (c != '\r') && (c != '\n'))
-					throw new ArgumentException ();
-			}
+			if (!XmlChar.IsWhitespace (ws))
+				throw new ArgumentException ("Invalid Whitespace");
 
 			CheckState ();