[corlib] Fixed StringBuilder construction bugs in marshalling caused by changes to...
[mono.git] / mcs / class / corlib / System.Resources / ResourceSet.cs
index 3964c244da11fed70cb11e58af5233892c619da6..5c27fc51a8f184017e98153c352818ef0dcbe916 100644 (file)
@@ -38,168 +38,196 @@ using System.Security.Permissions;
 namespace System.Resources
 {
        [Serializable]
-       public class ResourceSet : IDisposable
-
-#if (NET_1_1)
-                                               , IEnumerable
-#endif
-
+       [ComVisible (true)]
+       public class ResourceSet : IDisposable, IEnumerable
        {
-
+               [NonSerialized]
                protected IResourceReader Reader;
                protected Hashtable Table;
-               internal bool isDisposed = false;
+               bool resources_read;
+               [NonSerialized] Hashtable table_nocase;
 
                // Constructors
-               protected ResourceSet () {}
+               protected ResourceSet ()
+               {
+                       Table = new Hashtable ();
+                       resources_read = true;
+               }
 
                public ResourceSet (IResourceReader reader)
                {
                        if (reader == null)
-                               throw new ArgumentNullException ("The reader is null.");
+                               throw new ArgumentNullException ("reader");
+                       Table = new Hashtable ();
                        Reader = reader;
                }
+               
+               internal bool IsDisposed {
+                       get {
+                               return Table == null;
+                       }
+               }
 
                [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
                public ResourceSet (Stream stream)
                {
-                       if(stream==null) {
-                               throw new ArgumentNullException("stream is null");
-                       }
-
-                       if(!stream.CanRead) {
-                               throw new ArgumentException("stream is not readable");
-                       }
-                       
+                       Table = new Hashtable ();
                        Reader = new ResourceReader (stream);
                }
 
-               public ResourceSet (String fileName)
+               internal ResourceSet (UnmanagedMemoryStream stream)
                {
-                       if(fileName==null) {
-                               throw new ArgumentNullException("filename is null");
-                       }
-                       
+                       Table = new Hashtable ();
+                       Reader = new ResourceReader (stream);
+               }
+               
+               public ResourceSet (string fileName)
+               {
+                       Table = new Hashtable ();
                        Reader = new ResourceReader (fileName);
                }
 
                public virtual void Close ()
                {
-                       Dispose (true);
+                       Dispose ();
                }
 
                public void Dispose()
                {
                        Dispose (true);
+
+                       // If we are explicitly disposed, we can avoid finalization.
+                       GC.SuppressFinalize (this);
                }
 
                protected virtual void Dispose (bool disposing)
                {
                        if (disposing) {
-                               if(Reader!=null) {
+                               if(Reader != null)
                                        Reader.Close();
-                               }
                        }
 
                        Reader = null;
                        Table = null;
-                       
-                       isDisposed = true;
+                       table_nocase = null;
                }
 
                public virtual Type GetDefaultReader ()
                {
                        return (typeof (ResourceReader));
-               } 
+               }
+
                public virtual Type GetDefaultWriter ()
                {
                        return (typeof (ResourceWriter));
                }
 
-#if (NET_1_1)
-
                [ComVisible (false)]
                public virtual IDictionaryEnumerator GetEnumerator ()
                {
-                       if (Table == null)
-                               ReadResources ();
-                       return Table.GetEnumerator(); 
+                       if (IsDisposed)
+                               throw new ObjectDisposedException ("ResourceSet is closed.");
+                       ReadResources ();
+                       return Table.GetEnumerator();
                }
 
                IEnumerator IEnumerable.GetEnumerator ()
                {
-                       return this.GetEnumerator (); 
+                       return this.GetEnumerator ();
                }
 
-#endif
-
-               public virtual object GetObject (string name)
+               private object GetObjectInternal (string name, bool ignoreCase)
                {
                        if (name == null)
-                               throw new ArgumentNullException ("The name parameter is null.");
-                       if (Reader == null)
-                               throw new InvalidOperationException ("The ResourceSet has been closed.");
-
-                       if (Table == null) { 
-                               ReadResources ();
+                               throw new ArgumentNullException ("name");
+                       if (IsDisposed)
+                               throw new ObjectDisposedException ("ResourceSet is closed.");
+
+                       ReadResources ();
+
+                       if (!ignoreCase)
+                               return Table [name];
+
+                       if (table_nocase == null) {
+                               lock (Table) {
+                                       if (table_nocase == null) {
+                                               Hashtable ht = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
+                                               foreach (DictionaryEntry de in Table) {
+                                                       ht.Add (de.Key, de.Value);
+                                               }
+                                               table_nocase = ht;
+                                       }
+                               }
                        }
-                       
-                       return(Table[name]);
+                       return table_nocase [name];
+               }
+
+               public virtual object GetObject (string name)
+               {
+                       return GetObjectInternal (name, false);
                }
 
                public virtual object GetObject (string name, bool ignoreCase)
                {
-                       if (name == null)
-                               throw new ArgumentNullException ("The name parameter is null.");
-                       if (Reader == null)
-                               throw new InvalidOperationException ("ResourceSet has been closed.");
-                       if (Table == null)
-                               ReadResources ();
-
-                       if (ignoreCase) {
-                               foreach (DictionaryEntry de in Table) {
-                                       string key = (string) de.Key;
-                                       if (String.Compare (key, name, true, CultureInfo.InvariantCulture) == 0)
-                                               return de.Value;
-                               }
+                       return GetObjectInternal (name, ignoreCase);
+               }
+
+               private string GetStringInternal (string name, bool ignoreCase)
+               {
+                       object value = GetObject (name, ignoreCase);
+                       if (value == null)
                                return null;
-                       } else
-                               return Table[name];
+
+                       string s = (value as string);
+                       if (s == null)
+                               throw new InvalidOperationException (string.Format (
+                                       "Resource '{0}' is not a String. Use " +
+                                       "GetObject instead.", name));
+
+                       return s;
                }
 
                public virtual string GetString (string name)
                {
-                       Object o = GetObject (name);
-                       if (o == null)
-                               return null;
-                       if (o is string)
-                               return (string) o;
-                       throw new InvalidOperationException("Not a string");
+                       return GetStringInternal (name, false);
                }
 
                public virtual string GetString (string name, bool ignoreCase)
                {
-                       Object o = GetObject (name, ignoreCase);
-                       if (o == null)
-                               return null;
-                       if (o is string)
-                               return (string) o;
-                       throw new InvalidOperationException("Not a string");
+                       return GetStringInternal (name, ignoreCase);
                }
 
                protected virtual void ReadResources ()
                {
-                       if (Reader == null)
-                               throw new InvalidOperationException ("ResourceSet is closed.");
-                       
-                       IDictionaryEnumerator i = Reader.GetEnumerator();
+                       if (resources_read)
+                               return;
+
+                       if (IsDisposed)
+                               throw new ObjectDisposedException ("ResourceSet is closed.");
+                       lock (Table) {
+                               if (resources_read)
+                                       return;
+
+                               IDictionaryEnumerator i = Reader.GetEnumerator();
+                               i.Reset ();
+                               while (i.MoveNext ()) 
+                                       Table.Add (i.Key, i.Value);
+                               resources_read = true;
+                       }
+               }
 
-                       if (Table == null)
-                               Table = new Hashtable ();
-                       i.Reset ();
+               internal UnmanagedMemoryStream GetStream (string name, bool ignoreCase)
+               {
+                       if (IsDisposed)
+                               throw new ObjectDisposedException ("ResourceSet is closed.");
 
-                       while (i.MoveNext ()) 
-                               Table.Add (i.Key, i.Value);
+                       IDictionaryEnumerator i = Reader.GetEnumerator();
+                       i.Reset ();
+                       while (i.MoveNext ()){
+                               if (String.Compare (name, (string) i.Key, ignoreCase) == 0)
+                                       return ((ResourceReader.ResourceEnumerator) i).ValueAsStream;
+                       }
+                       return null;
                }
        }
 }