File: System\ServiceModel\StringUtil.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
// <copyright>
// Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
namespace System.ServiceModel
{
    internal static class StringUtil
    {
        private static readonly bool randomizedStringHashingEnabled;
 
        static StringUtil()
        {
            // StringComparer.InvariantCultureIgnoreCase.GetHashCode is a stable hash between 32 and 64 bits. 
            // Test the result of this GetHashCode against a known test vector to see if randomized hashing is enabled.
            randomizedStringHashingEnabled = StringComparer.InvariantCultureIgnoreCase.GetHashCode("The quick brown fox jumps over the lazy dog.") != 0x703e662e;
        }
 
        // This should be used instead of String.GetHashCode if the value should be
        // stable even if UseRandomizedStringHashing is enabled.
        internal static int GetNonRandomizedHashCode(string str)
        {
            if (!randomizedStringHashingEnabled)
            {
                return str.GetHashCode();
            }
 
            return GetStableHashCode(str);
        }
 
        // This is copied from the 32 bit implementation from String.GetHashCode.
        // Since ServiceModel is compiled for MSIL, we can't have different functionality
        // for 32 and 64 bits.
        [System.Security.SecuritySafeCritical]
        private static int GetStableHashCode(string str)
        {
            unsafe 
            {
                fixed (char* src = str) 
                {
                    int hash1 = (5381 << 16) + 5381;
                    int hash2 = hash1;
 
                    // 32 bit machines.
                    int* pint = (int*)src;
                    int len = str.Length;
                    while (len > 2)
                    {
                        hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0];
                        hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ pint[1];
                        pint += 2;
                        len  -= 4;
                    }
 
                    if (len > 0)
                    {
                        hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0];
                    }
 
                    return hash1 + (hash2 * 1566083941);
                }
            }
        }
    }
}