metadatamappinghashervisitor.hashsourcebuilder.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Mapping / metadatamappinghashervisitor.hashsourcebuilder.cs / 1508357 / metadatamappinghashervisitor.hashsourcebuilder.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics; 
using System.Data.Common.Utils;
using System.Security.Cryptography; 
using System.Globalization; 
using System.IO;
 

namespace System.Data.Mapping
{
    ///  
    /// This class keeps recomputing the hash and adding it to the front of the
    /// builder when the length of the string gets too long 
    ///  
    internal class CompressingHashBuilder : StringHashBuilder
    { 

        // this max comes from the value that Md5Hasher uses for a buffer size when it is reading
        // from a stream
        private const int HashCharacterCompressionThreshold = 0x1000 / 2;  // num bytes / 2 to convert to typical unicode char size 
        private const int SpacesPerIndent = 4;
 
        private int _indent = 0; 

        // we are starting the buffer at 1.5 times the number of bytes 
        // for the threshold
        internal CompressingHashBuilder(HashAlgorithm hashAlgorithm)
            : base(hashAlgorithm, (HashCharacterCompressionThreshold + (HashCharacterCompressionThreshold / 2)) * 2)
        { 
        }
 
        internal override void Append(string content) 
        {
            base.Append(string.Empty.PadLeft(SpacesPerIndent * _indent, ' ')); 
            base.Append(content);
            CompressHash();
        }
 
        internal override void AppendLine(string content)
        { 
            base.Append(string.Empty.PadLeft(SpacesPerIndent * _indent, ' ')); 
            base.AppendLine(content);
            CompressHash(); 
        }

        /// 
        /// add string like "typename Instance#1" 
        /// 
        ///  
        internal void AppendObjectStartDump(object o, int objectIndex) 
        {
            base.Append(string.Empty.PadLeft(SpacesPerIndent * _indent, ' ')); 
            base.Append(o.GetType().ToString());
            base.Append(" Instance#");
            base.AppendLine(objectIndex.ToString(CultureInfo.InvariantCulture));
            CompressHash(); 

            this._indent++; 
        } 

        internal void AppendObjectEndDump() 
        {
            Debug.Assert(this._indent > 0, "Indent and unindent should be paired");
            this._indent--;
        } 

 
        private void CompressHash() 
        {
            if(base.CharCount >= HashCharacterCompressionThreshold) 
            {
                string hash = ComputeHash();
                Clear();
                base.Append(hash); 
            }
        } 
    } 

 
    /// 
    /// this class collects several strings together, and allows you to (
    /// 
    internal class StringHashBuilder 
    {
        private HashAlgorithm _hashAlgorithm; 
        private const string NewLine = "\n"; 
        List _strings = new List();
        int _totalLength; 

        byte[] _cachedBuffer;

        internal StringHashBuilder(HashAlgorithm hashAlgorithm) 
        {
            _hashAlgorithm = hashAlgorithm; 
        } 

        internal StringHashBuilder(HashAlgorithm hashAlgorithm, int startingBufferSize) 
        :this(hashAlgorithm)
        {
            Debug.Assert(startingBufferSize > 0, "should be a non zero positive integer");
            _cachedBuffer = new byte[startingBufferSize]; 
        }
 
        internal int CharCount { get { return _totalLength; } } 

        internal virtual void Append(string s) 
        {
            InternalAppend(s);
        }
 
        internal virtual void AppendLine(string s)
        { 
            InternalAppend(s); 
            InternalAppend(NewLine);
        } 


        private void InternalAppend(string s)
        { 
            if (s.Length == 0)
                return; 
 
            _strings.Add(s);
            _totalLength += s.Length; 
        }

        internal string ComputeHash()
        { 
            int byteCount = GetByteCount();
            if(_cachedBuffer == null) 
            { 
                // assume it is a one time use, and
                // it will grow later if needed 
                _cachedBuffer = new byte[byteCount];
            }
            else if (_cachedBuffer.Length < byteCount)
            { 
                // grow it by what is needed at a minimum, or 1.5 times bigger
                // if that is bigger than what is needed this time.  We 
                // make it 1.5 times bigger in hopes to reduce the number of allocations (consider the 
                // case where the next one it 1 bigger)
                int bufferSize = Math.Max(_cachedBuffer.Length + (_cachedBuffer.Length / 2), byteCount); 
                _cachedBuffer = new byte[bufferSize];
            }

            int start = 0; 
            foreach (string s in _strings)
            { 
                start += Encoding.Unicode.GetBytes(s, 0, s.Length, _cachedBuffer, start); 
            }
            Debug.Assert(start == byteCount, "Did we use a different calculation for these?"); 

            byte[] hash = _hashAlgorithm.ComputeHash(_cachedBuffer, 0, byteCount);
            return ConvertHashToString(hash);
        } 

        internal void Clear() 
        { 
            _strings.Clear();
            _totalLength = 0; 
        }

        public override string ToString()
        { 
            StringBuilder builder = new StringBuilder();
            _strings.ForEach(s => builder.Append(s)); 
            return builder.ToString(); 
        }
 
        private int GetByteCount()
        {
            int count = 0;
            foreach (string s in _strings) 
            {
                count += Encoding.Unicode.GetByteCount(s); 
            } 

            return count; 
        }


        private static string ConvertHashToString(byte[] hash) 
        {
            StringBuilder stringData = new StringBuilder(hash.Length * 2); 
            // Loop through each byte of the data and format each one as a 
            // hexadecimal string
            for (int i = 0; i < hash.Length; i++) 
            {
                stringData.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture));
            }
            return stringData.ToString(); 
        }
 
        public static string ComputeHash(HashAlgorithm hashAlgorithm, string source) 
        {
            StringHashBuilder builder = new StringHashBuilder(hashAlgorithm); 
            builder.Append(source);
            return builder.ComputeHash();
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK