Merge pull request #4670 from BrzVlad/fix-sgen-testing
[mono.git] / mcs / class / System.Web / System.Web.Compilation / AspTokenizer.cs
index b915e7fd18143762d89f4731d6ff6d32e6a1df98..42f91cf7f46d77762647dcdb9b798db114e00c8f 100644 (file)
@@ -3,8 +3,10 @@
 //
 // Authors:
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//      Marek Habersack <mhabersack@novell.com>
 //
 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
+// (C) 2003-2009 Novell, Inc (http://novell.com)
 //
 
 //
@@ -32,6 +34,7 @@ using System;
 using System.Collections;
 using System.IO;
 using System.Text;
+using System.Security.Cryptography;
 
 namespace System.Web.Compilation
 {
@@ -48,6 +51,25 @@ namespace System.Web.Compilation
 
        class AspTokenizer
        {
+               const int CHECKSUM_BUF_SIZE = 8192;
+
+               class PutBackItem
+               {
+                       public readonly string Value;
+                       public readonly int Position;
+                       public readonly int CurrentToken;
+                       public readonly bool InTag;
+                       
+                       public PutBackItem (string value, int position, int currentToken, bool inTag)
+                       {
+                               Value = value;
+                               Position = position;
+                               CurrentToken = currentToken;
+                               InTag = inTag;
+                       }
+               }
+               
+               static char [] lfcr = new char [] { '\n', '\r' };
                TextReader sr;
                int current_token;
                StringBuilder sb, odds;
@@ -63,6 +85,14 @@ namespace System.Web.Compilation
                bool have_unget;
                int unget_value;
                string val;
+               Stack putBackBuffer;
+               MD5 checksum;
+               char[] checksum_buf = new char [CHECKSUM_BUF_SIZE];
+               int checksum_buf_pos = -1;
+               
+               public MD5 Checksum {
+                       get { return checksum; }
+               }
                
                public AspTokenizer (TextReader reader)
                {
@@ -81,18 +111,48 @@ namespace System.Web.Compilation
 
                public void put_back ()
                {
-                       if (hasPutBack)
+                       if (hasPutBack && !inTag)
                                throw new HttpException ("put_back called twice!");
                        
                        hasPutBack = true;
-                       position -= Value.Length;
+                       if (putBackBuffer == null)
+                               putBackBuffer = new Stack ();
+
+                       string val = Value;
+                       putBackBuffer.Push (new PutBackItem (val, position, current_token, inTag));
+                       position -= val.Length;
                }
                
                public int get_token ()
                {
-                       if (hasPutBack){
-                               hasPutBack = false;
-                               position += Value.Length;
+                       if (hasPutBack) {
+                               PutBackItem pbi;
+                               if (verbatim) {
+                                       pbi = putBackBuffer.Pop () as PutBackItem;
+                                       string value = pbi.Value;
+                                       switch (value.Length) {
+                                               case 0:
+                                                       // do nothing, CurrentToken will be used
+                                                       break;
+
+                                               case 1:
+                                                       pbi = new PutBackItem (String.Empty, pbi.Position, (int)value [0], false);
+                                                       break;
+
+                                               default:
+                                                       pbi = new PutBackItem (value, pbi.Position, (int)value [0], false);
+                                                       break;
+                                       }               
+                               } else
+                                       pbi = putBackBuffer.Pop () as PutBackItem;
+                               
+                               hasPutBack = putBackBuffer.Count > 0;
+                               position = pbi.Position;
+                               have_value = false;
+                               val = null;
+                               sb = new StringBuilder (pbi.Value);
+                               current_token = pbi.CurrentToken;
+                               inTag = pbi.InTag;
                                return current_token;
                        }
 
@@ -123,7 +183,35 @@ namespace System.Web.Compilation
                        position--;
                        col--;
                }
+
+               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 + 1 >= CHECKSUM_BUF_SIZE)
+                                       TransformNextBlock (checksum_buf_pos + 1, false);
+                               checksum_buf [++checksum_buf_pos] = (char)c;
+                       } else
+                               TransformNextBlock (checksum_buf_pos + 1, true);
+               }
+
                int read_char ()
                {
                        int c;
@@ -132,10 +220,12 @@ namespace System.Web.Compilation
                                have_unget = false;
                        } else {
                                c = sr.Read ();
+                               UpdateChecksum (c);
                        }
 
                        if (c == '\r' && sr.Peek () == '\n') {
                                c = sr.Read ();
+                               UpdateChecksum (c);
                                position++;
                        }
 
@@ -236,8 +326,12 @@ namespace System.Web.Compilation
                                }
 
                                if (inTag && current_token == '%' && "@#=".IndexOf ((char) c) != -1){
+                                       if (odds.Length == 0 || odds.ToString ().IndexOfAny (lfcr) < 0) {
+                                               sb.Append ((char) c);
+                                               return c;
+                                       }
                                        sb.Append ((char) c);
-                                       return c;
+                                       continue;
                                }
 
                                if (inTag && c == '-' && sr.Peek () == '-'){