1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004 Novell, Inc.
23 // Duncan Mak duncan@ximian.com
24 // Nick Drochak ndrochak@gol.com
25 // Paolo Molaro lupus@ximian.com
30 using System.Collections;
31 using System.Resources;
34 using System.ComponentModel;
35 using System.Globalization;
36 using System.Runtime.Serialization.Formatters.Binary;
38 namespace System.Resources
40 public class ResXResourceReader : IResourceReader, IDisposable
47 public ResXResourceReader (Stream stream)
50 throw new ArgumentNullException ("Value cannot be null.");
53 throw new ArgumentException ("Stream was not readable.");
59 public ResXResourceReader (string fileName)
61 stream = File.OpenRead (fileName);
66 reader = new XmlTextReader (stream);
67 hasht = new Hashtable ();
69 if (!IsStreamValid()){
70 throw new ArgumentException("Stream is not a valid .resx file! It was possibly truncated.");
75 static string get_attr (XmlTextReader reader, string name) {
76 if (!reader.HasAttributes)
78 for (int i = 0; i < reader.AttributeCount; i++) {
79 reader.MoveToAttribute (i);
80 if (String.Compare (reader.Name, name, true) == 0) {
81 string v = reader.Value;
82 reader.MoveToElement ();
86 reader.MoveToElement ();
90 static string get_value (XmlTextReader reader, string name) {
91 bool gotelement = false;
92 while (reader.Read ()) {
93 if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, name, true) == 0) {
100 while (reader.Read ()) {
101 if (reader.NodeType == XmlNodeType.Text || reader.NodeType == XmlNodeType.CDATA) {
102 string v = reader.Value;
105 else if (reader.NodeType == XmlNodeType.EndElement && reader.Value == string.Empty)
107 string v = reader.Value;
114 private bool IsStreamValid() {
115 bool gotroot = false;
116 bool gotmime = false;
118 while (reader.Read ()) {
119 if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, "root", true) == 0) {
126 while (reader.Read ()) {
127 if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, "resheader", true) == 0) {
128 string v = get_attr (reader, "name");
129 if (v != null && String.Compare (v, "resmimetype", true) == 0) {
130 v = get_value (reader, "value");
131 if (String.Compare (v, "text/microsoft-resx", true) == 0) {
136 } else if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, "data", true) == 0) {
137 /* resheader apparently can appear anywhere, so we collect
138 * the data even if we haven't validated yet.
140 string n = get_attr (reader, "name");
142 string v = get_value (reader, "value");
150 private void load_data ()
152 while (reader.Read ()) {
153 if (reader.NodeType == XmlNodeType.Element && String.Compare (reader.Name, "data", true) == 0) {
154 string n = get_attr (reader, "name");
155 string t = get_attr (reader, "type");
156 string mt = get_attr (reader, "mimetype");
158 Type tt = t == null ? null : Type.GetType (t);
160 if (t != null && tt == null) {
161 throw new SystemException ("The type `" + t +"' could not be resolved");
163 if (tt == typeof (ResXNullRef)) {
169 string val = get_value (reader, "value");
170 if (mt != null && tt != null) {
171 TypeConverter c = TypeDescriptor.GetConverter (tt);
172 v = c.ConvertFrom (Convert.FromBase64String (val));
173 } else if (tt != null) {
174 TypeConverter c = TypeDescriptor.GetConverter (tt);
175 v = c.ConvertFromString (val);
176 } else if (mt != null) {
177 byte [] data = Convert.FromBase64String (val);
178 BinaryFormatter f = new BinaryFormatter ();
179 using (MemoryStream s = new MemoryStream (data)) {
180 v = f.Deserialize (s);
197 public IDictionaryEnumerator GetEnumerator () {
199 throw new InvalidOperationException("ResourceReader is closed.");
202 return hasht.GetEnumerator ();
206 IEnumerator IEnumerable.GetEnumerator ()
208 return ((IResourceReader) this).GetEnumerator();
212 void IDisposable.Dispose ()
214 // FIXME: is this all we need to do?
218 } // public sealed class ResXResourceReader
219 } // namespace System.Resources