Просмотр исходного кода

2009-03-25 Marek Habersack <[email protected]>

	* AspTokenizer.cs: MD5 checksum calculation happens here. It's
	done incrementally as characters are read.

	* AspParser.cs: the MD5 checksum is no longer computed here. Moved
	to AspTokenizer.
	After parsing, both the tokenizer and the string reader are
	disposed of.

svn path=/trunk/mcs/; revision=130245
Marek Habersack 17 лет назад
Родитель
Сommit
8b21628c27

+ 72 - 53
mcs/class/System.Web/System.Web.Compilation/AspParser.cs

@@ -52,17 +52,16 @@ namespace System.Web.Compilation
 		static readonly object textParsedEvent = new object ();
 #if NET_2_0
 		static readonly object parsingCompleteEvent = new object();
-		
-		byte[] md5checksum;
 #endif
 		AspTokenizer tokenizer;
 		int beginLine, endLine;
 		int beginColumn, endColumn;
 		int beginPosition, endPosition;
 		string filename;
-		string fileText;
 		string verbatimID;
-
+		string fileText;
+		StringReader fileReader;
+		
 		EventHandlerList events = new EventHandlerList ();
 		
 		public event ParseErrorHandler Error {
@@ -90,18 +89,20 @@ namespace System.Web.Compilation
 		public AspParser (string filename, TextReader input)
 		{
 			this.filename = filename;
-			fileText = input.ReadToEnd ();
-#if NET_2_0
-			MD5 md5 = MD5.Create ();
-			md5checksum = md5.ComputeHash (Encoding.UTF8.GetBytes (fileText));
-#endif
-			StringReader reader = new StringReader (fileText);
-			tokenizer = new AspTokenizer (reader);
+			this.fileText = input.ReadToEnd ();
+			this.fileReader = new StringReader (this.fileText);
+			tokenizer = new AspTokenizer (this.fileReader);
 		}
 
 #if NET_2_0
 		public byte[] MD5Checksum {
-			get { return md5checksum; }
+			get {
+				MD5 checksum = tokenizer.Checksum;
+				if (checksum == null)
+					return new byte[0];
+				
+				return checksum.Hash;
+			}
 		}
 #endif
 		
@@ -122,12 +123,17 @@ namespace System.Web.Compilation
 		}
 
 		public string FileText {
-			get { return fileText; }
+			get {
+				if (fileText != null)
+					return fileText;
+				
+				return null;
+			}
 		}
 		
 		public string PlainText {
 			get {
-				if (beginPosition >= endPosition)
+				if (beginPosition >= endPosition || fileText == null)
 					return null;
 
 				return fileText.Substring (beginPosition, endPosition - beginPosition);
@@ -144,7 +150,7 @@ namespace System.Web.Compilation
 				verbatimID = value;
 			}
 		}
-		
+
 		bool Eat (int expected_token)
 		{
 			if (tokenizer.get_token () != expected_token) {
@@ -173,60 +179,73 @@ namespace System.Web.Compilation
 
 		public void Parse ()
 		{
+			if (tokenizer == null) {
+				OnError ("AspParser not initialized properly.");
+				return;
+			}
+			
 			int token;
 			string id;
 			TagAttributes attributes;
 			TagType tagtype = TagType.Text;
 			StringBuilder text =  new StringBuilder ();
 
-			while ((token = tokenizer.get_token ()) != Token.EOF) {
-				BeginElement ();
+			try {
+				while ((token = tokenizer.get_token ()) != Token.EOF) {
+					BeginElement ();
 
-				if (tokenizer.Verbatim){
-					string end_verbatim = "</" + verbatimID + ">";
-					string verbatim_text = GetVerbatim (token, end_verbatim);
+					if (tokenizer.Verbatim){
+						string end_verbatim = "</" + verbatimID + ">";
+						string verbatim_text = GetVerbatim (token, end_verbatim);
 
-					if (verbatim_text == null)
-						OnError ("Unexpected EOF processing " + verbatimID);
+						if (verbatim_text == null)
+							OnError ("Unexpected EOF processing " + verbatimID);
 
-					tokenizer.Verbatim = false;
+						tokenizer.Verbatim = false;
 
-					EndElement ();
-					endPosition -= end_verbatim.Length;
-					OnTextParsed (verbatim_text);
-					beginPosition = endPosition;
-					endPosition += end_verbatim.Length;
-					OnTagParsed (TagType.Close, verbatimID, null);
-					continue;
-				}
-				
-				if (token == '<') {
-					GetTag (out tagtype, out id, out attributes);
-					EndElement ();
-					if (tagtype == TagType.ServerComment)
+						EndElement ();
+						endPosition -= end_verbatim.Length;
+						OnTextParsed (verbatim_text);
+						beginPosition = endPosition;
+						endPosition += end_verbatim.Length;
+						OnTagParsed (TagType.Close, verbatimID, null);
 						continue;
+					}
+				
+					if (token == '<') {
+						GetTag (out tagtype, out id, out attributes);
+						EndElement ();
+						if (tagtype == TagType.ServerComment)
+							continue;
 
-					if (tagtype == TagType.Text)
-						OnTextParsed (id);
-					else
-						OnTagParsed (tagtype, id, attributes);
+						if (tagtype == TagType.Text)
+							OnTextParsed (id);
+						else
+							OnTagParsed (tagtype, id, attributes);
 
-					continue;
-				}
+						continue;
+					}
 
-				if (tokenizer.Value.Trim () == "" && tagtype == TagType.Directive) {
-					continue;
-				}
+					if (tokenizer.Value.Trim () == "" && tagtype == TagType.Directive) {
+						continue;
+					}
 
-				text.Length = 0;
-				do {
-					text.Append (tokenizer.Value);
-					token = tokenizer.get_token ();
-				} while (token != '<' && token != Token.EOF);
+					text.Length = 0;
+					do {
+						text.Append (tokenizer.Value);
+						token = tokenizer.get_token ();
+					} while (token != '<' && token != Token.EOF);
 
-				tokenizer.put_back ();
-				EndElement ();
-				OnTextParsed (text.ToString ());
+					tokenizer.put_back ();
+					EndElement ();
+					OnTextParsed (text.ToString ());
+				}
+			} finally {
+				if (fileReader != null) {
+					fileReader.Close ();
+					fileReader = null;
+				}
+				tokenizer = null;
 			}
 
 #if NET_2_0

+ 48 - 0
mcs/class/System.Web/System.Web.Compilation/AspTokenizer.cs

@@ -32,6 +32,7 @@ using System;
 using System.Collections;
 using System.IO;
 using System.Text;
+using System.Security.Cryptography;
 
 namespace System.Web.Compilation
 {
@@ -48,6 +49,9 @@ namespace System.Web.Compilation
 
 	class AspTokenizer
 	{
+#if NET_2_0
+		const int CHECKSUM_BUF_SIZE = 8192;
+#endif
 		class PutBackItem
 		{
 			public readonly string Value;
@@ -79,6 +83,15 @@ namespace System.Web.Compilation
 		int unget_value;
 		string val;
 		Stack putBackBuffer;
+#if NET_2_0
+		MD5 checksum;
+		char[] checksum_buf = new char [CHECKSUM_BUF_SIZE];
+		int checksum_buf_pos = -1;
+		
+		public MD5 Checksum {
+			get { return checksum; }
+		}
+#endif
 		
 		public AspTokenizer (TextReader reader)
 		{
@@ -149,7 +162,36 @@ namespace System.Web.Compilation
 			position--;
 			col--;
 		}
+
+#if NET_2_0
+		void TransformNextBlock (int count, bool final)
+		{
+			byte[] input = Encoding.UTF8.GetBytes (checksum_buf, 0, count);
+
+			if (checksum == null)
+				checksum = MD5.Create ();
+			
+			if (final)
+				checksum.TransformFinalBlock (input, 0, input.Length);
+			else
+				checksum.TransformBlock (input, 0, input.Length, input, 0);
+			input = null;
+			
+			checksum_buf_pos = -1;
+		}
 		
+		void UpdateChecksum (int c)
+		{
+			bool final = c == -1;
+
+			if (!final) {
+				if (checksum_buf_pos >= CHECKSUM_BUF_SIZE)
+					TransformNextBlock (checksum_buf_pos + 1, false);
+				checksum_buf [++checksum_buf_pos] = (char)c;
+			} else
+				TransformNextBlock (checksum_buf_pos + 1, true);
+		}
+#endif
 		int read_char ()
 		{
 			int c;
@@ -158,10 +200,16 @@ namespace System.Web.Compilation
 				have_unget = false;
 			} else {
 				c = sr.Read ();
+#if NET_2_0
+				UpdateChecksum (c);
+#endif
 			}
 
 			if (c == '\r' && sr.Peek () == '\n') {
 				c = sr.Read ();
+#if NET_2_0
+				UpdateChecksum (c);
+#endif
 				position++;
 			}
 

+ 8 - 0
mcs/class/System.Web/System.Web.Compilation/ChangeLog

@@ -1,5 +1,13 @@
 2009-03-25  Marek Habersack  <[email protected]>
 
+	* AspTokenizer.cs: MD5 checksum calculation happens here. It's
+	done incrementally as characters are read.
+
+	* AspParser.cs: the MD5 checksum is no longer computed here. Moved
+	to AspTokenizer.
+	After parsing, both the tokenizer and the string reader are
+	disposed of.
+
 	* AssemblyBuilder.cs: renamed CopyFile to CopyFileWithChecksum, in
 	prepration for future inclusion of checksum and line pragmas in
 	the file being copied.