diff options
author | Wade Berrier <wade@mono-cvs.ximian.com> | 2006-01-20 06:01:55 +0300 |
---|---|---|
committer | Wade Berrier <wade@mono-cvs.ximian.com> | 2006-01-20 06:01:55 +0300 |
commit | 24906dde223bd634fe2b5ec231ba399eb01ed85e (patch) | |
tree | 41105c34861eec3b735807df22bb7b25baef78f9 /mcs/class/Managed.Windows.Forms/System.Resources | |
parent | bf9916e270e2a7c449da248c0afcf667766e3fa2 (diff) | |
parent | 0694b14ef614fcbbd9b12a2b1a5ccd202fe7089a (diff) |
oops, recopy from trunkmono-1-1-13-2
svn path=/branches/mono-1-1-13/mcs/; revision=55819
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/System.Resources')
6 files changed, 928 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Resources/ChangeLog b/mcs/class/Managed.Windows.Forms/System.Resources/ChangeLog new file mode 100644 index 00000000000..307e6d6624e --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/System.Resources/ChangeLog @@ -0,0 +1,101 @@ +2005-12-05 Peter Bartok <pbartok@novell.com> + + * ResXResourceReader.cs: Removed previous patch. More than just Byte[] + has that mime type and the patch was causing things to fail. + Since our writer no longer emits the mimetype this should be fine. + +2005-12-01 Robert Jordan <robertj@gmx.net> + + * ResXResourceReader.cs: Handle mimetype="application/x-microsoft.net.object.bytearray.base64" correctly. Fixes the decoding of System.Byte[]. + * ResXResourceWriter.cs: Fixed AddResource (string, object) to pass + control to AddResource (string, byte[]) if the value parameter is + a byte[]. Removed the emitting of the mimetype attribute for + System.Byte[]. + +2005-11-30 Peter Bartok <pbartok@novell.com> + + * ResXResourceReader.cs: Handle System.Byte[] encodings without + needing a typeconverter (This fixes bug #76414) + +2005-11-30 Robert Jordan <robertj@gmx.net> + + * ResXResourceReader.cs, ResXResourceWriter.cs: Made string conversions + culture-invariant. + * ResXResourceWriter.cs: Fixed AddResource (string, object) to emit + the type attribute when the object has a type converter. + +2005-10-04 Peter Bartok <pbartok@novell.com> + + * ResXResourceReader.cs, ResXResourceWriter.cs: Added call + to GC.SuppressFinalize() in dispose method. Fixes #76330 + +2005-05-13 Peter Bartok <pbartok@novell.com> + + * ResXResourceWriter.cs: + - Fixed/Improved AddResource(), now only uses string converter if + the converter supports both directions + - Added ability for AddResource(string, object) to detect if + a byte[] converter is supported for the object, if so it now calls + AddResource(string, byte[]) for those + - WriteBytes: Changed to write it's base64 output as pretty + as Microsoft's, inserting newlines every 80 chars + - WriteBytes: Added output of mimetype even if type is specified + +2005-05-11 Peter Bartok <pbartok@novell.com> + + * ResXResourceSet.cs: Implemented + * ResXFileRef.cs: Implemented + * ResXNullRef.cs: Added missing attribute + * ResXResourceReader.cs: Implemented missing .ctor()s and other + assorted fun stuff, should now be complete + * ResResourceWriter.cs: Implemented missing methods and added + missing static fields + +2005-04-14 Jackson Harper <jackson@ximian.com> + + * ResXResourceReader.cs: Use serialization on values that have a + mime type set but no type. + +2005-02-16 Peter Bartok <pbartok@novell.com> + + * ResXResourceReader.cs, ResXResourceWriter.cs: Removed sealed + attribute from classes + +2005-02-12 Geoff Norton (gnorton@customerdna.com) + + * ResXResourceReader.cs (load_data): Undo previous change as + ResXNullRef is now properly handled. + * ResXNullRef.cs: Added + +2005-02-11 Geoff Norton (gnorton@customerdna.com) + + * ResXResourceReader.cs (load_data): Temporarily re-introduce the + old failure for types that we cannot yet handle to allow Npgsql to + build. + +2005-02-11 Raja R Harinath <rharinath@novell.com> + + * ResXResourceReader.cs (load_data): Make exception more informative. + +2005-02-10 Geoff Norton <gnorton@customerdna.com> + + * ResXResourceReader.cs: Implement the ability to convert the + MS Base64 encoded objects. Implement the ability to convert objects + to their type rather than just to string. + +2004-11-08 14:28 pbartok + + * ResXResourceReader.cs: + - BenM's Fix for bug 68260 + +2004-10-13 08:14 pbartok + + * ResXResourceReader.cs: + - Patch by joel.reed@ddiworld.com (joel) to handle CDATA sections. + +2004-08-29 22:36 pbartok + + * ResXResourceReader.cs, ResXResourceWriter.cs: + - Transfered files from previous version of System.Windows.Forms + - Added full copyright header + diff --git a/mcs/class/Managed.Windows.Forms/System.Resources/ResXFileRef.cs b/mcs/class/Managed.Windows.Forms/System.Resources/ResXFileRef.cs new file mode 100644 index 00000000000..52081d265da --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/System.Resources/ResXFileRef.cs @@ -0,0 +1,105 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2005 Novell, Inc. (http://www.novell.com) +// +// Authors: +// Peter Bartok (pbartok@novell.com) +// +// + +// COMPLETE + +using System; +using System.ComponentModel; +using System.IO; +using System.Reflection; + +namespace System.Resources { + [Serializable] + [TypeConverter(typeof(ResXFileRef.Converter))] + public class ResXFileRef { + #region Converter Class + public class Converter : TypeConverter { + #region Constructors + public Converter() { + } + #endregion // Constructors + + #region Methods + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { + return sourceType == typeof(string); + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { + return destinationType == typeof(string); + } + + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { + string[] parts; + byte[] buffer; + + if ( !(value is String)) { + return base.ConvertFrom(context, culture, value); + } + + parts = ((string)value).Split(';'); + + using (FileStream file = new FileStream(parts[0], FileMode.Open, FileAccess.Read, FileShare.Read)) { + buffer = new byte[file.Length]; + + file.Read(buffer, 0, (int)file.Length); + } + + return Activator.CreateInstance(Type.GetType(parts[1]), BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance, null, new object[] { new MemoryStream(buffer) }, culture); + } + + public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { + if (destinationType != typeof(String)) { + return base.ConvertTo (context, culture, value, destinationType); + } + + return ((ResXFileRef)value).ToString(); + } + #endregion // Methods + } + #endregion // Converter Class + + #region Local Variables + private string filename; + private string typename; + #endregion // Local Variables + + #region Public Constructors + public ResXFileRef(string fileName, string typeName) { + this.filename = fileName; + this.typename = typeName; + } + #endregion // Public Constructors + + #region Public Instance Properties + #endregion // Public Instance Properties + + #region Public Instance Methods + public override string ToString() { + return filename + ";" + typename; + } + #endregion // Public Instance Methods + } +} diff --git a/mcs/class/Managed.Windows.Forms/System.Resources/ResXNullRef.cs b/mcs/class/Managed.Windows.Forms/System.Resources/ResXNullRef.cs new file mode 100644 index 00000000000..d172feccea9 --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/System.Resources/ResXNullRef.cs @@ -0,0 +1,34 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2005 Novell, Inc. +// +// Authors: +// Geoff Norton gnorton@customerdna.com +// + +using System; + +namespace System.Resources +{ + [Serializable] + internal class ResXNullRef + { + } +} diff --git a/mcs/class/Managed.Windows.Forms/System.Resources/ResXResourceReader.cs b/mcs/class/Managed.Windows.Forms/System.Resources/ResXResourceReader.cs new file mode 100644 index 00000000000..cd0e027d0b8 --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/System.Resources/ResXResourceReader.cs @@ -0,0 +1,289 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2004-2005 Novell, Inc. +// +// Authors: +// Duncan Mak duncan@ximian.com +// Nick Drochak ndrochak@gol.com +// Paolo Molaro lupus@ximian.com +// Peter Bartok pbartok@novell.com +// + +// COMPLETE + +using System; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Globalization; +using System.IO; +using System.Resources; +using System.Runtime.Serialization.Formatters.Binary; +using System.Xml; + +namespace System.Resources +{ + public class ResXResourceReader : IResourceReader, IDisposable + { + #region Local Variables + private Stream stream; + private XmlTextReader reader; + private Hashtable hasht; + private ITypeResolutionService typeresolver; + #endregion // Local Variables + + #region Constructors & Destructor + public ResXResourceReader (Stream stream) + { + if (stream == null) + throw new ArgumentNullException ("Value cannot be null."); + + if (!stream.CanRead) + throw new ArgumentException ("Stream was not readable."); + + this.stream = stream; + basic_setup (); + } + + public ResXResourceReader (Stream stream, ITypeResolutionService typeresolver) : this(stream) { + this.typeresolver = typeresolver; + } + + public ResXResourceReader (string fileName) + { + stream = File.OpenRead (fileName); + basic_setup (); + } + + public ResXResourceReader (string fileName, ITypeResolutionService typeresolver) : this(fileName) { + this.typeresolver = typeresolver; + } + + public ResXResourceReader(TextReader reader) { + this.reader = new XmlTextReader(reader); + this.hasht = new Hashtable(); + + load_data(); + } + + public ResXResourceReader (TextReader reader, ITypeResolutionService typeresolver) : this(reader) { + this.typeresolver = typeresolver; + } + + ~ResXResourceReader() { + Dispose(false); + } + #endregion // Constructors & Destructor + + + #region Private Methods + void basic_setup () { + reader = new XmlTextReader (stream); + hasht = new Hashtable (); + + if (!IsStreamValid()){ + throw new ArgumentException("Stream is not a valid .resx file! It was possibly truncated."); + } + load_data (); + } + + static string get_attr (XmlTextReader reader, string name) { + if (!reader.HasAttributes) + return null; + for (int i = 0; i < reader.AttributeCount; i++) { + reader.MoveToAttribute (i); + if (String.Compare (reader.Name, name, true) == 0) { + string v = reader.Value; + reader.MoveToElement (); + return v; + } + } + reader.MoveToElement (); + return null; + } + + static string get_value (XmlTextReader reader, string name) { + bool gotelement = false; + while (reader.Read ()) { + if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, name, true) == 0) { + gotelement = true; + break; + } + } + if (!gotelement) + return null; + while (reader.Read ()) { + if (reader.NodeType == XmlNodeType.Text || reader.NodeType == XmlNodeType.CDATA) { + string v = reader.Value; + return v; + } + else if (reader.NodeType == XmlNodeType.EndElement && reader.Value == string.Empty) + { + string v = reader.Value; + return v; + } + } + return null; + } + + private bool IsStreamValid() { + bool gotroot = false; + bool gotmime = false; + + while (reader.Read ()) { + if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, "root", true) == 0) { + gotroot = true; + break; + } + } + if (!gotroot) + return false; + while (reader.Read ()) { + if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, "resheader", true) == 0) { + string v = get_attr (reader, "name"); + if (v != null && String.Compare (v, "resmimetype", true) == 0) { + v = get_value (reader, "value"); + if (String.Compare (v, "text/microsoft-resx", true) == 0) { + gotmime = true; + break; + } + } + } else if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, "data", true) == 0) { + /* resheader apparently can appear anywhere, so we collect + * the data even if we haven't validated yet. + */ + string n = get_attr (reader, "name"); + if (n != null) { + string v = get_value (reader, "value"); + hasht [n] = v; + } + } + } + return gotmime; + } + + private void load_data () + { + while (reader.Read ()) { + if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, "data", true) == 0) { + string n = get_attr (reader, "name"); + string t = get_attr (reader, "type"); + string mt = get_attr (reader, "mimetype"); + + Type tt = t == null ? null : Type.GetType (t); + + if (t != null && tt == null) { + throw new SystemException ("The type `" + t +"' could not be resolved"); + } + if (tt == typeof (ResXNullRef)) { + hasht [n] = null; + continue; + } + if (n != null) { + object v = null; + string val = get_value (reader, "value"); + + if (mt != null && tt != null) { + TypeConverter c = TypeDescriptor.GetConverter (tt); + v = c.ConvertFrom (Convert.FromBase64String (val)); + } else if (tt != null) { + // MS seems to handle Byte[] without any mimetype :-( + if (t.StartsWith("System.Byte[], mscorlib")) { + v = Convert.FromBase64String(val); + } else { + TypeConverter c = TypeDescriptor.GetConverter (tt); + v = c.ConvertFromInvariantString (val); + } + } else if (mt != null) { + byte [] data = Convert.FromBase64String (val); + BinaryFormatter f = new BinaryFormatter (); + using (MemoryStream s = new MemoryStream (data)) { + v = f.Deserialize (s); + } + } else { + v = val; + } + hasht [n] = v; + } + } + } + } + + private Type GetType(string type) { + if (typeresolver == null) { + return Type.GetType(type); + } else { + return typeresolver.GetType(type); + } + } + #endregion // Private Methods + + #region Public Methods + public void Close () + { + if (stream != null) { + stream.Close (); + stream = null; + } + + if (reader != null) { + reader.Close(); + reader = null; + } + } + + public IDictionaryEnumerator GetEnumerator () { + if (null == stream){ + throw new InvalidOperationException("ResourceReader is closed."); + } + else { + return hasht.GetEnumerator (); + } + } + + IEnumerator IEnumerable.GetEnumerator () + { + return ((IResourceReader) this).GetEnumerator(); + } + + void IDisposable.Dispose () + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) { + if (disposing) { + Close(); + } + } + + public static ResXResourceReader FromFileContents(string fileContents) { + return new ResXResourceReader(new StringReader(fileContents)); + } + + public static ResXResourceReader FromFileContents(string fileContents, ITypeResolutionService typeResolver) { + return new ResXResourceReader(new StringReader(fileContents), typeResolver); + } + + #endregion // Public Methods + + } // public sealed class ResXResourceReader +} // namespace System.Resources diff --git a/mcs/class/Managed.Windows.Forms/System.Resources/ResXResourceSet.cs b/mcs/class/Managed.Windows.Forms/System.Resources/ResXResourceSet.cs new file mode 100644 index 00000000000..5fc589a41d6 --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/System.Resources/ResXResourceSet.cs @@ -0,0 +1,63 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2005 Novell, Inc. (http://www.novell.com) +// +// Authors: +// Peter Bartok (pbartok@novell.com) +// +// + +// COMPLETE + +using System; +using System.IO; +using System.Collections; + +namespace System.Resources { + public class ResXResourceSet : ResourceSet { + #region Local Variables + + #endregion // Local Variables + + #region Public Constructors + public ResXResourceSet(Stream stream) { + this.Reader = new ResXResourceReader(stream); + this.Table = new Hashtable(); + this.ReadResources(); + } + + public ResXResourceSet(string fileName) { + this.Reader = new ResXResourceReader(fileName); + this.Table = new Hashtable(); + this.ReadResources(); + } + #endregion // Public Constructors + + #region Public Instance Methods + public override Type GetDefaultReader() { + return typeof(ResXResourceReader); + } + + public override Type GetDefaultWriter() { + return typeof(ResXResourceWriter); + } + #endregion // Public Instance Methods + } +} diff --git a/mcs/class/Managed.Windows.Forms/System.Resources/ResXResourceWriter.cs b/mcs/class/Managed.Windows.Forms/System.Resources/ResXResourceWriter.cs new file mode 100644 index 00000000000..76da29c1cef --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/System.Resources/ResXResourceWriter.cs @@ -0,0 +1,336 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2004-2005 Novell, Inc. +// +// Authors: +// Duncan Mak duncan@ximian.com +// Gonzalo Paniagua Javier gonzalo@ximian.com +// Peter Bartok pbartok@novell.com +// + +// COMPLETE + +using System.ComponentModel; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Xml; + +namespace System.Resources +{ + public class ResXResourceWriter : IResourceWriter, IDisposable + { + #region Local Variables + private string filename; + private Stream stream; + private TextWriter textwriter; + private XmlTextWriter writer; + private bool written; + #endregion // Local Variables + + #region Static Fields + public static readonly string BinSerializedObjectMimeType = "application/x-microsoft.net.object.binary.base64"; + public static readonly string ByteArraySerializedObjectMimeType = "application/x-microsoft.net.object.bytearray.base64"; + public static readonly string DefaultSerializedObjectMimeType = BinSerializedObjectMimeType; + public static readonly string ResMimeType = "text/microsoft-resx"; + public static readonly string ResourceSchema = schema;
+ public static readonly string SoapSerializedObjectMimeType = "application/x-microsoft.net.object.soap.base64"; + public static readonly string Version = "1.3"; + #endregion // Static Fields + + #region Constructors & Destructor + public ResXResourceWriter (Stream stream) + { + if (stream == null) + throw new ArgumentNullException ("stream"); + + if (stream.CanWrite == false) + throw new ArgumentException ("stream is not writable.", "stream"); + + this.stream = stream; + } + + public ResXResourceWriter (TextWriter textwriter) + { + if (textwriter == null) + throw new ArgumentNullException ("textwriter"); + + this.textwriter = textwriter; + } + + public ResXResourceWriter (string fileName) + { + if (fileName == null) + throw new ArgumentNullException ("fileName"); + + this.filename = fileName; + } + + ~ResXResourceWriter() { + Dispose(false); + } + #endregion // Constructors & Destructor + + void InitWriter () + { + if (filename != null) { + stream = File.OpenWrite (filename); + textwriter = new StreamWriter (stream, Encoding.UTF8); + } + + writer = new XmlTextWriter (textwriter); + writer.Formatting = Formatting.Indented; + writer.WriteStartDocument (); + writer.WriteStartElement ("root"); + writer.WriteRaw (schema); + WriteHeader ("resmimetype", "text/microsoft-resx"); + WriteHeader ("version", "1.3"); + WriteHeader ("reader", typeof (ResXResourceReader).AssemblyQualifiedName); + WriteHeader ("writer", typeof (ResXResourceWriter).AssemblyQualifiedName); + } + + void WriteHeader (string name, string value) + { + writer.WriteStartElement ("resheader"); + writer.WriteAttributeString ("name", name); + writer.WriteStartElement ("value"); + writer.WriteString (value); + writer.WriteEndElement (); + writer.WriteEndElement (); + } + + void WriteNiceBase64(byte[] value, int offset, int length) { + string b64; + StringBuilder sb; + int pos; + int inc; + string ins; + + b64 = Convert.ToBase64String(value, offset, length); + + // Wild guess; two extra newlines, and one newline/tab pair for every 80 chars + sb = new StringBuilder(b64, b64.Length + ((b64.Length + 160) / 80) * 3); + pos = 0; + inc = 80 + Environment.NewLine.Length + 1; + ins = Environment.NewLine + "\t"; + while (pos < sb.Length) { + sb.Insert(pos, ins); + pos += inc; + } + sb.Insert(sb.Length, Environment.NewLine); + writer.WriteString(sb.ToString()); + } + + void WriteBytes (string name, string typename, byte [] value, int offset, int length) + { + writer.WriteStartElement ("data"); + writer.WriteAttributeString ("name", name); + + if (typename != null) { + writer.WriteAttributeString ("type", typename); + writer.WriteStartElement ("value"); + WriteNiceBase64(value, offset, length); + } else { + writer.WriteAttributeString ("mimetype", + "application/x-microsoft.net.object.binary.base64"); + writer.WriteStartElement ("value"); + writer.WriteBase64 (value, offset, length); + } + + writer.WriteEndElement (); + writer.WriteEndElement (); + } + + void WriteBytes (string name, string typename, byte [] value) + { + WriteBytes (name, typename, value, 0, value.Length); + } + + void WriteString (string name, string value) + { + WriteString (name, value, null); + } + + void WriteString (string name, string value, string typename) + { + writer.WriteStartElement ("data"); + writer.WriteAttributeString ("name", name); + if (typename != null) + writer.WriteAttributeString ("type", typename); + writer.WriteStartElement ("value"); + writer.WriteString (value); + writer.WriteEndElement (); + writer.WriteEndElement (); + writer.WriteWhitespace ("\n "); + } + + public void AddResource (string name, byte [] value) + { + if (name == null) + throw new ArgumentNullException ("name"); + + if (value == null) + throw new ArgumentNullException ("value"); + + if (written) + throw new InvalidOperationException ("The resource is already generated."); + + if (writer == null) + InitWriter (); + + WriteBytes (name, value.GetType ().AssemblyQualifiedName, value); + } + + public void AddResource (string name, object value) + { + if (value is string) { + AddResource (name, (string) value); + return; + } + + if (value is byte[]) { + AddResource (name, (byte[]) value); + return; + } + + if (name == null) + throw new ArgumentNullException ("name"); + + if (value == null) + throw new ArgumentNullException ("value"); + + if (written) + throw new InvalidOperationException ("The resource is already generated."); + + if (writer == null) + InitWriter (); + + TypeConverter converter = TypeDescriptor.GetConverter (value); + if (converter != null && converter.CanConvertTo (typeof (string)) && converter.CanConvertFrom (typeof (string))) { + string str = (string) converter.ConvertToInvariantString (value); + WriteString (name, str, value.GetType ().AssemblyQualifiedName); + return; + } + + if (converter != null && converter.CanConvertTo (typeof (byte[])) && converter.CanConvertFrom (typeof (byte[]))) { + byte[] b = (byte[]) converter.ConvertTo (value, typeof (byte[])); + WriteBytes (name, value.GetType().AssemblyQualifiedName, b); + return; + } + + MemoryStream ms = new MemoryStream (); + BinaryFormatter fmt = new BinaryFormatter (); + try { + fmt.Serialize (ms, value); + } catch (Exception e) { + throw new InvalidOperationException ("Cannot add a " + value.GetType () + + "because it cannot be serialized: " + + e.Message); + } + + WriteBytes (name, null, ms.GetBuffer (), 0, (int) ms.Length); + ms.Close (); + } + + public void AddResource (string name, string value) + { + if (name == null) + throw new ArgumentNullException ("name"); + + if (value == null) + throw new ArgumentNullException ("value"); + + if (written) + throw new InvalidOperationException ("The resource is already generated."); + + if (writer == null) + InitWriter (); + + WriteString (name, value); + } + + public void Close () + { + if (!written) { + Generate (); + } + + if (writer != null) { + writer.Close (); + stream = null; + filename = null; + textwriter = null; + } + } + + public void Dispose () + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void Generate () + { + if (written) + throw new InvalidOperationException ("The resource is already generated."); + + written = true; + writer.WriteEndElement (); + writer.Flush (); + } + + protected virtual void Dispose(bool disposing) { + if (disposing) { + Close(); + } + } + + static string schema = @" + <xsd:schema id='root' xmlns='' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:msdata='urn:schemas-microsoft-com:xml-msdata'> + <xsd:element name='root' msdata:IsDataSet='true'> + <xsd:complexType> + <xsd:choice maxOccurs='unbounded'> + <xsd:element name='data'> + <xsd:complexType> + <xsd:sequence> + <xsd:element name='value' type='xsd:string' minOccurs='0' msdata:Ordinal='1' /> + <xsd:element name='comment' type='xsd:string' minOccurs='0' msdata:Ordinal='2' /> + </xsd:sequence> + <xsd:attribute name='name' type='xsd:string' msdata:Ordinal='1' /> + <xsd:attribute name='type' type='xsd:string' msdata:Ordinal='3' /> + <xsd:attribute name='mimetype' type='xsd:string' msdata:Ordinal='4' /> + </xsd:complexType> + </xsd:element> + <xsd:element name='resheader'> + <xsd:complexType> + <xsd:sequence> + <xsd:element name='value' type='xsd:string' minOccurs='0' msdata:Ordinal='1' /> + </xsd:sequence> + <xsd:attribute name='name' type='xsd:string' use='required' /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> +".Replace ("'", "\""); + } +} + |