Merge pull request #697 from linquize/atom-bug
[mono.git] / mcs / class / corlib / System.Collections / CaseInsensitiveHashCodeProvider.cs
index 87179d771a2670256a1720fe370150dbd6c2e2e6..0a273dacc8f9e9dc67d30d7f689943fa37b5e271 100644 (file)
@@ -4,10 +4,9 @@
 // Authors:
 //   Sergey Chaban (serge@wildwestsoftware.com)
 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
+//   Sebastien Pouliot  <sebastien@ximian.com>
 //
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 //
 
 using System.Globalization;
+using System.Runtime.InteropServices;
 
 namespace System.Collections
 {
        [Serializable]
-       [MonoTODO ("Fix serialization compatibility with MS.NET")]
-#if NET_2_0
+       [ComVisible(true)]
        [Obsolete ("Please use StringComparer instead.")]
+#if INSIDE_CORLIB
+       public
+#else
+       internal
 #endif
-       public class CaseInsensitiveHashCodeProvider : IHashCodeProvider
+       class CaseInsensitiveHashCodeProvider : IHashCodeProvider
        {
-               static readonly CaseInsensitiveHashCodeProvider singleton = new CaseInsensitiveHashCodeProvider ();
-               static readonly CaseInsensitiveHashCodeProvider singletonInvariant = new CaseInsensitiveHashCodeProvider (true);
+               static readonly CaseInsensitiveHashCodeProvider singletonInvariant = new CaseInsensitiveHashCodeProvider (
+                       CultureInfo.InvariantCulture);
+               static CaseInsensitiveHashCodeProvider singleton;
+               static readonly object sync = new object ();
 
-               CultureInfo culture;
+               TextInfo m_text; // must match MS name for serialization
 
                // Public instance constructor
                public CaseInsensitiveHashCodeProvider ()
                {
-                       culture = CultureInfo.CurrentCulture;
-               }
-
-               private CaseInsensitiveHashCodeProvider (bool invariant)
-               {
-                       // leave culture == null
+                       CultureInfo culture = CultureInfo.CurrentCulture;
+                       if (!AreEqual (culture, CultureInfo.InvariantCulture))
+                               m_text = CultureInfo.CurrentCulture.TextInfo;
                }
 
                public CaseInsensitiveHashCodeProvider (CultureInfo culture)
                {
                        if (culture == null)
                                throw new ArgumentNullException ("culture");
-                       if (culture.LCID != CultureInfo.InvariantCulture.LCID)
-                               this.culture = culture;
-                       // else leave culture == null
+                       if (!AreEqual (culture, CultureInfo.InvariantCulture))
+                               m_text = culture.TextInfo;
                }
 
                //
@@ -71,15 +72,42 @@ namespace System.Collections
 
                public static CaseInsensitiveHashCodeProvider Default {
                        get {
-                               return singleton;
+                               // MS actually constructs a new instance on each call, for
+                               // performance reasons we're only constructing a new instance
+                               // if the CurrentCulture changes
+                               lock (sync) {
+                                       if (singleton == null) {
+                                               singleton = new CaseInsensitiveHashCodeProvider ();
+                                       } else if (singleton.m_text == null) {
+                                               if (!AreEqual (CultureInfo.CurrentCulture, CultureInfo.InvariantCulture))
+                                                       singleton = new CaseInsensitiveHashCodeProvider ();
+                                       } else if (!AreEqual (singleton.m_text, CultureInfo.CurrentCulture)) {
+                                               singleton = new CaseInsensitiveHashCodeProvider ();
+                                       }
+                                       return singleton;
+                               }
                        }
                }
 
-#if NET_1_1
-               public
+               static bool AreEqual (CultureInfo a, CultureInfo b)
+               {
+#if !NET_2_1
+                       return a.LCID == b.LCID;
 #else
-               internal
+                       return a.Name == b.Name;
 #endif
+               }
+
+               static bool AreEqual (TextInfo info, CultureInfo culture)
+               {
+#if !NET_2_1
+                       return info.LCID == culture.LCID;
+#else
+                       return info.CultureName == culture.Name;
+#endif
+               }
+
+               public
                static CaseInsensitiveHashCodeProvider DefaultInvariant {
                        get {
                                return singletonInvariant;
@@ -103,16 +131,15 @@ namespace System.Collections
                        int h = 0;
                        char c;
 
-                       if (culture != null && culture.LCID != CultureInfo.InvariantCulture.LCID) {
-                               str = str.ToLower (culture);
+                       if ((m_text != null) && !AreEqual (m_text, CultureInfo.InvariantCulture)) {
+                               str = m_text.ToLower (str);
                                for (int i = 0; i < str.Length; i++) {
                                        c = str [i];
                                        h = h * 31 + c;
                                }
-                       }
-                       else {
+                       } else {
                                for (int i = 0; i < str.Length; i++) {
-                                       c = Char.ToLowerInvariant (str [i]);
+                                       c = Char.ToLower (str [i], CultureInfo.InvariantCulture);
                                        h = h * 31 + c;
                                }
                        }